@weasel-js/core 1.10.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/CHANGELOG.md +168 -0
  2. package/README.md +33 -0
  3. package/dist/affordances/composeAffordanceLayer.js +21 -21
  4. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  5. package/dist/affordances/hitAffordanceRegions.js +48 -32
  6. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  7. package/dist/affordances/pathAnchors.js +50 -28
  8. package/dist/affordances/pathAnchors.js.map +1 -1
  9. package/dist/affordances/rotateCursor.js +12 -0
  10. package/dist/affordances/rotateCursor.js.map +1 -0
  11. package/dist/affordances/rotationHandle.js +40 -43
  12. package/dist/affordances/rotationHandle.js.map +1 -1
  13. package/dist/animation/rig/rigNode.js +9 -3
  14. package/dist/animation/rig/rigNode.js.map +1 -1
  15. package/dist/animation/rig/rigSeat.js +46 -13
  16. package/dist/animation/rig/rigSeat.js.map +1 -1
  17. package/dist/animation/rig/skinBinding.js +22 -14
  18. package/dist/animation/rig/skinBinding.js.map +1 -1
  19. package/dist/barrel/canvas.js +29 -28
  20. package/dist/barrel/interactions.js +33 -32
  21. package/dist/barrel/paths.js +11 -10
  22. package/dist/barrel/routing.js +49 -48
  23. package/dist/barrel/scene.js +10 -10
  24. package/dist/barrel/viewport.js +24 -21
  25. package/dist/canvas/Canvas.js +6 -17
  26. package/dist/canvas/Canvas.js.map +1 -1
  27. package/dist/canvas/CanvasView.js +34 -37
  28. package/dist/canvas/CanvasView.js.map +1 -1
  29. package/dist/canvas/CursorCoordsHud.js +3 -3
  30. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  31. package/dist/canvas/DrawCanvas.js +3 -3
  32. package/dist/canvas/DrawCanvas.js.map +1 -1
  33. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +24 -23
  34. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  35. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +40 -49
  36. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  37. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +297 -259
  38. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  39. package/dist/canvas/SceneCanvas/features.js +3 -24
  40. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  41. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +97 -0
  42. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
  43. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  44. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  45. package/dist/canvas/SceneCanvas/scenePointQuery.js +50 -0
  46. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
  47. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +52 -0
  48. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
  49. package/dist/canvas/SceneCanvas/useActionTunings.js +17 -0
  50. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
  51. package/dist/canvas/SceneCanvas/useCanvasCamera.js +37 -29
  52. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
  53. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +11 -11
  54. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
  55. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +45 -109
  56. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  57. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +49 -41
  58. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +64 -96
  60. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  61. package/dist/canvas/SceneCanvas/worldPointAt.js +3 -4
  62. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  63. package/dist/canvas/SceneCanvas.js +77 -80
  64. package/dist/canvas/SceneCanvas.js.map +1 -1
  65. package/dist/canvas/SceneViewCanvas.js +3 -3
  66. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  67. package/dist/canvas/SurfaceCanvas.js +40 -0
  68. package/dist/canvas/SurfaceCanvas.js.map +1 -0
  69. package/dist/canvas/adapterDerivedPath.js +13 -13
  70. package/dist/canvas/adapterDerivedPath.js.map +1 -1
  71. package/dist/canvas/adapterPickSource.js +34 -0
  72. package/dist/canvas/adapterPickSource.js.map +1 -0
  73. package/dist/canvas/affordanceAt.js +1 -1
  74. package/dist/canvas/affordanceAt.js.map +1 -1
  75. package/dist/canvas/buildSceneLayer.js.map +1 -1
  76. package/dist/canvas/buildSceneTree.js +56 -34
  77. package/dist/canvas/buildSceneTree.js.map +1 -1
  78. package/dist/canvas/copiesAbove.js +27 -0
  79. package/dist/canvas/copiesAbove.js.map +1 -0
  80. package/dist/canvas/defaultDrawOne.js +24 -23
  81. package/dist/canvas/defaultDrawOne.js.map +1 -1
  82. package/dist/canvas/deps/editAnchors.js +45 -50
  83. package/dist/canvas/deps/editAnchors.js.map +1 -1
  84. package/dist/canvas/deps/hitTestArea.js +30 -15
  85. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  86. package/dist/canvas/deps/insert.js +134 -100
  87. package/dist/canvas/deps/insert.js.map +1 -1
  88. package/dist/canvas/deps/layout.js +9 -15
  89. package/dist/canvas/deps/layout.js.map +1 -1
  90. package/dist/canvas/derivedPath.js +53 -29
  91. package/dist/canvas/derivedPath.js.map +1 -1
  92. package/dist/canvas/insertPreviewExtent.js +33 -31
  93. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  94. package/dist/canvas/overChildren.js +29 -0
  95. package/dist/canvas/overChildren.js.map +1 -0
  96. package/dist/canvas/paintedCursorLayer.js.map +1 -1
  97. package/dist/canvas/pickReach.js +23 -0
  98. package/dist/canvas/pickReach.js.map +1 -0
  99. package/dist/canvas/pickWalk.js +51 -80
  100. package/dist/canvas/pickWalk.js.map +1 -1
  101. package/dist/canvas/sceneAdapter.js +14 -35
  102. package/dist/canvas/sceneAdapter.js.map +1 -1
  103. package/dist/canvas/sceneSlotWiring.js +11 -10
  104. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  105. package/dist/canvas/sceneViewRender.js +38 -44
  106. package/dist/canvas/sceneViewRender.js.map +1 -1
  107. package/dist/canvas/useCanvasView.js +42 -44
  108. package/dist/canvas/useCanvasView.js.map +1 -1
  109. package/dist/canvas/useSceneAdapter.js +22 -0
  110. package/dist/canvas/useSceneAdapter.js.map +1 -0
  111. package/dist/canvas/useSurfaceInput.js +13 -16
  112. package/dist/canvas/useSurfaceInput.js.map +1 -1
  113. package/dist/canvas/viewRegistry.js +31 -23
  114. package/dist/canvas/viewRegistry.js.map +1 -1
  115. package/dist/canvas/wrapNodeOutput.js +7 -2
  116. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  117. package/dist/clipboard.d.ts +1 -1
  118. package/dist/{clone-2a5hVbBd.d.ts → clone-C0eADtS0.d.ts} +13 -13
  119. package/dist/clone.d.ts +2 -2
  120. package/dist/core/geometry/poseDescriptor.js +49 -23
  121. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  122. package/dist/core/geometry/regionHit.js +2 -2
  123. package/dist/core/geometry/regionHit.js.map +1 -1
  124. package/dist/core/geometry/targetFrame.js.map +1 -1
  125. package/dist/core/layers/children.js +1 -3
  126. package/dist/core/layers/children.js.map +1 -1
  127. package/dist/core/ops/create.js +2 -2
  128. package/dist/core/ops/create.js.map +1 -1
  129. package/dist/core/ops/delete.js +19 -23
  130. package/dist/core/ops/delete.js.map +1 -1
  131. package/dist/core/ops/reorder/index.js +3 -7
  132. package/dist/core/ops/reorder/index.js.map +1 -1
  133. package/dist/core/ops/reorder/setChildOrder.js +2 -4
  134. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  135. package/dist/core/ops/reparent.js +0 -1
  136. package/dist/core/ops/reparent.js.map +1 -1
  137. package/dist/core/ops/slot.js +3 -6
  138. package/dist/core/ops/slot.js.map +1 -1
  139. package/dist/core/pages/fitViewToPage.js +15 -0
  140. package/dist/core/pages/fitViewToPage.js.map +1 -0
  141. package/dist/core/pages/pages.js +65 -0
  142. package/dist/core/pages/pages.js.map +1 -0
  143. package/dist/core/pages/pagesLayer.js +27 -0
  144. package/dist/core/pages/pagesLayer.js.map +1 -0
  145. package/dist/core/paint/meshKindLazy.js +2 -2
  146. package/dist/core/paint/meshKindLazy.js.map +1 -1
  147. package/dist/core/scene/NodeProperties.js.map +1 -1
  148. package/dist/core/scene/composeFrame.js.map +1 -1
  149. package/dist/core/scene/composePose.js +58 -20
  150. package/dist/core/scene/composePose.js.map +1 -1
  151. package/dist/core/scene/effectivePose.js +5 -1
  152. package/dist/core/scene/effectivePose.js.map +1 -1
  153. package/dist/core/scene/historyFacade.js +19 -13
  154. package/dist/core/scene/historyFacade.js.map +1 -1
  155. package/dist/core/scene/nodeFnFields.js +7 -0
  156. package/dist/core/scene/nodeFnFields.js.map +1 -1
  157. package/dist/core/scene/outerOps.js +2 -1
  158. package/dist/core/scene/outerOps.js.map +1 -1
  159. package/dist/core/scene/reconcileSpecs.js +1 -1
  160. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  161. package/dist/core/scene/sceneRecording.js +2 -1
  162. package/dist/core/scene/sceneRecording.js.map +1 -1
  163. package/dist/core/scene/types.js.map +1 -1
  164. package/dist/core/viewport/screenSlop.js.map +1 -1
  165. package/dist/core/viewport/useDecayLoop.js +28 -30
  166. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  167. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
  168. package/dist/core/viewport/useViewAnimation.js +70 -69
  169. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  170. package/dist/core/viewport/view.js +8 -5
  171. package/dist/core/viewport/view.js.map +1 -1
  172. package/dist/core/viewport/zoomAt.js +11 -2
  173. package/dist/core/viewport/zoomAt.js.map +1 -1
  174. package/dist/{cornerHandles-BEshc4z3.d.ts → cornerHandles-BSKbyuvQ.d.ts} +1 -1
  175. package/dist/features/paths/editablePath.js +24 -8
  176. package/dist/features/paths/editablePath.js.map +1 -1
  177. package/dist/features/paths/index.js +4 -4
  178. package/dist/features/paths/shapeGenerator.js +89 -0
  179. package/dist/features/paths/shapeGenerator.js.map +1 -0
  180. package/dist/features/paths/usePathEdit.js +13 -13
  181. package/dist/features/poseRun/usePoseRun.js +25 -25
  182. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  183. package/dist/features/text/useSceneTextEdit.js +82 -64
  184. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  185. package/dist/features/viewports/viewResolver.js +28 -24
  186. package/dist/features/viewports/viewResolver.js.map +1 -1
  187. package/dist/icons/SliceIcon.js +24 -0
  188. package/dist/icons/SliceIcon.js.map +1 -0
  189. package/dist/index.d.ts +956 -581
  190. package/dist/index.js +260 -251
  191. package/dist/interactions/actions/align/align.js +9 -9
  192. package/dist/interactions/actions/align/align.js.map +1 -1
  193. package/dist/interactions/actions/booleans/booleans.js +18 -18
  194. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  195. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  196. package/dist/interactions/actions/clone/action.js +35 -30
  197. package/dist/interactions/actions/clone/action.js.map +1 -1
  198. package/dist/interactions/actions/defaults/anchorEditing.js +56 -59
  199. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  200. package/dist/interactions/actions/defaults/anchorHandles.js +42 -0
  201. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
  202. package/dist/interactions/actions/defaults/anchorJoin.js +92 -0
  203. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
  204. package/dist/interactions/actions/defaults/bendSegment.js +46 -0
  205. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
  206. package/dist/interactions/actions/defaults/copySubtree.js +1 -1
  207. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  208. package/dist/interactions/actions/defaults/duplicate.js +32 -17
  209. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  210. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -7
  211. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  212. package/dist/interactions/actions/defaults/icons/anchorIcons.js +75 -0
  213. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +1 -0
  214. package/dist/interactions/actions/defaults/icons/editIcons.js +35 -8
  215. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -1
  216. package/dist/interactions/actions/defaults/insertPathAnchor.js +16 -31
  217. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  218. package/dist/interactions/actions/defaults/nudge.js +28 -23
  219. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  220. package/dist/interactions/actions/defaults/pinchZoom.js +29 -29
  221. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  222. package/dist/interactions/actions/defaults/segmentUnder.js +22 -0
  223. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
  224. package/dist/interactions/actions/defaults/viewportZoom.js +82 -79
  225. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  226. package/dist/interactions/actions/distribute/distribute.js +8 -8
  227. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  228. package/dist/interactions/actions/edit-anchors/action.js +58 -55
  229. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  230. package/dist/interactions/actions/edit-anchors/preview.js +26 -0
  231. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
  232. package/dist/interactions/actions/edit-anchors/symmetry.js +11 -0
  233. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
  234. package/dist/interactions/actions/flip/action.js.map +1 -1
  235. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  236. package/dist/interactions/actions/insert/action.js +37 -30
  237. package/dist/interactions/actions/insert/action.js.map +1 -1
  238. package/dist/interactions/actions/insert/frame.js +9 -2
  239. package/dist/interactions/actions/insert/frame.js.map +1 -1
  240. package/dist/interactions/actions/insert/repositionAction.js +31 -0
  241. package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
  242. package/dist/interactions/actions/lasso-select/action.js +32 -32
  243. package/dist/interactions/actions/move/action.js +29 -25
  244. package/dist/interactions/actions/move/action.js.map +1 -1
  245. package/dist/interactions/actions/move/behaviors/snapToContainer.js +12 -6
  246. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  247. package/dist/interactions/actions/move/capture.js +32 -23
  248. package/dist/interactions/actions/move/capture.js.map +1 -1
  249. package/dist/interactions/actions/move/frame.js +2 -14
  250. package/dist/interactions/actions/move/frame.js.map +1 -1
  251. package/dist/interactions/actions/move/session.js +1 -1
  252. package/dist/interactions/actions/move/session.js.map +1 -1
  253. package/dist/interactions/actions/move/translate.js.map +1 -1
  254. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  255. package/dist/interactions/actions/outlines/replaceWithPaths.js +13 -13
  256. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
  257. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
  258. package/dist/interactions/actions/pathCommands/cutJoin.js +102 -0
  259. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
  260. package/dist/interactions/actions/pathCommands/livePathEdit.js +64 -0
  261. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
  262. package/dist/interactions/actions/pathCommands/pathNodes.js +99 -0
  263. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
  264. package/dist/interactions/actions/pathCommands/simplifyOffset.js +42 -0
  265. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
  266. package/dist/interactions/actions/resize/action.js +31 -20
  267. package/dist/interactions/actions/resize/action.js.map +1 -1
  268. package/dist/interactions/actions/resize/commit.js.map +1 -1
  269. package/dist/interactions/actions/resize/frame.js +29 -15
  270. package/dist/interactions/actions/resize/frame.js.map +1 -1
  271. package/dist/interactions/actions/resize/replay.js +47 -0
  272. package/dist/interactions/actions/resize/replay.js.map +1 -0
  273. package/dist/interactions/actions/resize/session.js +49 -35
  274. package/dist/interactions/actions/resize/session.js.map +1 -1
  275. package/dist/interactions/actions/resolveOverlays.js +2 -1
  276. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  277. package/dist/interactions/actions/rotate/action.js +40 -25
  278. package/dist/interactions/actions/rotate/action.js.map +1 -1
  279. package/dist/interactions/actions/rotate/frame.js +1 -1
  280. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  281. package/dist/interactions/actions/rotate/replay.js +22 -0
  282. package/dist/interactions/actions/rotate/replay.js.map +1 -0
  283. package/dist/interactions/actions/rotate/session.js +42 -32
  284. package/dist/interactions/actions/rotate/session.js.map +1 -1
  285. package/dist/interactions/actions/transform-again/action.js +63 -0
  286. package/dist/interactions/actions/transform-again/action.js.map +1 -0
  287. package/dist/interactions/actions/transform-again/memory.js +35 -0
  288. package/dist/interactions/actions/transform-again/memory.js.map +1 -0
  289. package/dist/interactions/actions/useStandardActions.js +101 -83
  290. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  291. package/dist/move.d.ts +4 -4
  292. package/dist/{originProjection-PPT88jZv.d.ts → originProjection-CoNVpITV.d.ts} +1 -1
  293. package/dist/resize.d.ts +3 -3
  294. package/dist/style.css +1 -1
  295. package/dist/tools/builtin/ellipse/useEllipseTool.js +16 -15
  296. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  297. package/dist/tools/builtin/line/useLineTool.js +16 -15
  298. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  299. package/dist/tools/builtin/pen/usePenTool.js +111 -111
  300. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  301. package/dist/tools/builtin/pickTopMostHit.js +11 -14
  302. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  303. package/dist/tools/builtin/polygon/usePolygonTool.js +17 -15
  304. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  305. package/dist/tools/builtin/rect/useRectTool.js +15 -14
  306. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  307. package/dist/tools/builtin/select/adapterPointQuery.js +22 -18
  308. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  309. package/dist/tools/builtin/select/selectionContributions.js +1 -1
  310. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  311. package/dist/tools/builtin/select/useSelectTool.js +2 -1
  312. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  313. package/dist/tools/builtin/slice/useSliceTool.js +42 -40
  314. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  315. package/dist/tools/builtin/star/useStarTool.js +18 -16
  316. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  317. package/dist/tools/builtin/text/useTextTool.js +2 -2
  318. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  319. package/dist/{types-CIKDwlsP.d.ts → types-DBbbCy0i.d.ts} +22 -15
  320. package/dist/version.js +1 -1
  321. package/package.json +22 -22
  322. package/dist/canvas/surface.module.js +0 -6
  323. package/dist/canvas/surface.module.js.map +0 -1
  324. package/dist/canvas/surfaceBox.js +0 -16
  325. package/dist/canvas/surfaceBox.js.map +0 -1
  326. package/dist/layout/arrivals.js +0 -33
  327. package/dist/layout/arrivals.js.map +0 -1
@@ -2,73 +2,77 @@ import { planeMap as e } from "../core/viewport/parallax.js";
2
2
  import { resolveDerivedPath as t } from "../core/scene/derivedPath.js";
3
3
  import { clipCarrier as n } from "./planeClips.js";
4
4
  import { findShapeSilhouette as r } from "./NodeShape.js";
5
- import { adapterDerivedPathOf as i } from "./adapterDerivedPath.js";
6
- import { asNodeId as a } from "../core/scene/types.js";
7
- import { sceneDerivedPathOf as o, scenePaintedPoseOf as s, showsComputedPath as c } from "./derivedPath.js";
5
+ import { asNodeId as i } from "../core/scene/types.js";
6
+ import { sceneDerivedPathOf as a, scenePaintedPoseOf as o, showsComputedPath as s } from "./derivedPath.js";
7
+ import { reaches as c } from "./pickReach.js";
8
+ import { adapterPickSource as l } from "./adapterPickSource.js";
9
+ import { invert as u } from "@weasel-js/geom";
8
10
  //#region src/canvas/pickWalk.ts
9
- var l = [];
10
- function u(e, t, n) {
11
+ var d = [];
12
+ function f(e, t, n) {
11
13
  return e.kind === "container" ? typeof e.clipFromPose == "function" ? e.clipFromPose(t) : r(e, t, { derivedPath: n }) : null;
12
14
  }
13
- function d(e, t) {
14
- let r = t.includeContainers ?? !0, i = t.includeLocked === !0 ? void 0 : e.isLocked, a = [], o = /* @__PURE__ */ new Map(), s = n(e.planeOf ?? null), c = (t) => {
15
+ function p(e, t) {
16
+ let r = t.includeContainers ?? !0, i = t.includeLocked === !0 ? void 0 : e.isLocked, a = [], o = /* @__PURE__ */ new Map(), s = n(e.planeOf ?? null), l = (t) => {
15
17
  let n = o.get(t.id);
16
18
  if (n !== void 0) return n;
17
- let r = u(t, e.poseOf(t), e.derivedPathOf?.(t));
19
+ let r = f(t, e.poseOf(t), e.derivedPathOf?.(t));
18
20
  return o.set(t.id, r), r;
19
- }, l = /* @__PURE__ */ new Map(), d = (n) => {
21
+ }, d = /* @__PURE__ */ new Map(), p = (t) => {
22
+ let n = d.get(t.id);
23
+ if (n === void 0) {
24
+ let r = t.kind === "container" ? t.copiesFromPose : void 0;
25
+ n = (r ? r(e.poseOf(t), t) ?? [] : []).map(u).filter((e) => e !== null), d.set(t.id, n);
26
+ }
27
+ return n;
28
+ }, m = /* @__PURE__ */ new Map(), h = (n) => {
20
29
  if (n === void 0 || e.planeOf === void 0) return t;
21
- let r = l.get(n);
30
+ let r = m.get(n);
22
31
  if (r === void 0) {
23
32
  let i = e.planeOf(n);
24
- r = i === null ? t : t.inPlane?.(i) ?? null, l.set(n, r);
33
+ r = i === null ? t : t.inPlane?.(i) ?? null, m.set(n, r);
25
34
  }
26
35
  return r;
27
- };
28
- for (let t of e.order()) {
36
+ }, g = e.order(), _ = g.some((e) => e.kind === "container" && typeof e.copiesFromPose == "function");
37
+ for (let t of g) {
29
38
  if (!r && t.kind === "container" || t.pickable === !1 || t.layer !== void 0 && e.layerIsPainted?.(t.layer) === !1 || e.alphaOf !== void 0 && e.alphaOf(t.id) <= 0 || i !== void 0 && i(t)) continue;
30
- let n = d(t.layer);
39
+ let n = h(t.layer);
31
40
  if (n === null) continue;
32
- let o = e.poseOf(t), l = e.derivedPathOf?.(t);
33
- if (!n.hits(t, o, l)) continue;
34
- let u = !1;
35
- for (let r of e.parentsOf(t)) {
36
- let e = c(r);
37
- if (e !== null && !n.clipAdmits(s(e, r.layer, t.layer), t, o, l)) {
38
- u = !0;
39
- break;
40
- }
41
- }
42
- u || a.push(t.id);
41
+ let o = e.poseOf(t), u = e.derivedPathOf?.(t);
42
+ c(t, o, u, n, () => e.parentsOf(t), _, {
43
+ clipOf: l,
44
+ copiesOf: p,
45
+ carry: s
46
+ }) && a.push(t.id);
43
47
  }
44
48
  return a;
45
49
  }
46
- function f(e) {
50
+ function m(e) {
47
51
  let t = null;
48
52
  for (let n of e.layers ?? []) n.locked === !0 && (t ??= /* @__PURE__ */ new Set()).add(n.id);
49
53
  if (t === null) return null;
50
54
  let n = t;
51
55
  return (t) => {
52
- let r = e.get(a(t)), i = /* @__PURE__ */ new Set();
53
- for (; r !== void 0 && !i.has(r.id);) {
56
+ let r = e.get(i(t)), a = /* @__PURE__ */ new Set();
57
+ for (; r !== void 0 && !a.has(r.id);) {
54
58
  if (n.has(r.layer)) return !0;
55
- i.add(r.id), r = r.parent === null ? void 0 : e.get(r.parent);
59
+ a.add(r.id), r = r.parent === null ? void 0 : e.get(r.parent);
56
60
  }
57
61
  return !1;
58
62
  };
59
63
  }
60
- function p(e) {
64
+ function h(e) {
61
65
  let t = /* @__PURE__ */ new Set();
62
66
  for (let n of e ?? []) n.visible === !1 && t.add(n.id);
63
67
  return t;
64
68
  }
65
- function m(e, n = {}) {
66
- let r = p(e.layers), i = f(e), { getPose: u, alphaOf: d, layerIsPainted: m } = n, g = null, _ = typeof e.overrides?.ids == "function";
67
- if (!d && _) for (let t of e.overrides.ids()) {
69
+ function g(e, n = {}) {
70
+ let r = h(e.layers), c = m(e), { getPose: l, alphaOf: u, layerIsPainted: f } = n, p = null, g = typeof e.overrides?.ids == "function";
71
+ if (!u && g) for (let t of e.overrides.ids()) {
68
72
  let n = e.overrides.read(t)?.alpha;
69
- n !== void 0 && n <= 0 && (g ??= /* @__PURE__ */ new Set()).add(t);
73
+ n !== void 0 && n <= 0 && (p ??= /* @__PURE__ */ new Set()).add(t);
70
74
  }
71
- let v = d ?? (_ ? g ? (e) => +!g.has(e) : void 0 : (t) => e.overrides.read(a(t))?.alpha ?? 1), y = s(e), b = u ? (e) => u(e.id) : (e) => y(e), x = (t) => e.childrenOf(t), S = (n) => {
75
+ let v = u ?? (g ? p ? (e) => +!p.has(e) : void 0 : (t) => e.overrides.read(i(t))?.alpha ?? 1), y = o(e), b = l ? (e) => l(e.id) : (e) => y(e), x = (t) => e.childrenOf(t), S = (n) => {
72
76
  let r = e.get(n);
73
77
  if (r !== void 0) return {
74
78
  node: r,
@@ -77,10 +81,10 @@ function m(e, n = {}) {
77
81
  return t(r, S, x);
78
82
  }
79
83
  };
80
- }, C = u ? null : o(e), w = (n) => {
84
+ }, C = l ? null : a(e), w = (n) => {
81
85
  let r = n;
82
- return C ? c(e, r) ? C(r) : null : r.dependsOn === void 0 ? null : t(r, S, x);
83
- }, T = n.camera ? h(e.layers, n.camera) : null;
86
+ return C ? s(e, r) ? C(r) : null : r.dependsOn === void 0 ? null : t(r, S, x);
87
+ }, T = n.camera ? _(e.layers, n.camera) : null;
84
88
  return {
85
89
  ...T ? { planeOf: T } : {},
86
90
  order: () => e.renderOrderNodes(),
@@ -88,62 +92,29 @@ function m(e, n = {}) {
88
92
  poseOf: b,
89
93
  parentsOf(t) {
90
94
  let n = t.parent ?? null;
91
- if (n === null) return l;
92
- let r = [], i = /* @__PURE__ */ new Set();
93
- for (; n !== null && !i.has(n);) {
94
- i.add(n);
95
- let t = e.get(a(n));
95
+ if (n === null) return d;
96
+ let r = [], a = /* @__PURE__ */ new Set();
97
+ for (; n !== null && !a.has(n);) {
98
+ a.add(n);
99
+ let t = e.get(i(n));
96
100
  if (!t) break;
97
101
  r.push(t), n = t.parent ?? null;
98
102
  }
99
103
  return r;
100
104
  },
101
105
  ...v ? { alphaOf: v } : {},
102
- ...i ? { isLocked: (e) => i(e.id) } : {},
103
- ...r.size > 0 || m ? { layerIsPainted: (e) => !r.has(e) && (m === void 0 || m(e)) } : {}
106
+ ...c ? { isLocked: (e) => c(e.id) } : {},
107
+ ...r.size > 0 || f ? { layerIsPainted: (e) => !r.has(e) && (f === void 0 || f(e)) } : {}
104
108
  };
105
109
  }
106
- function h(t, n) {
110
+ function _(t, n) {
107
111
  let r = null;
108
112
  for (let i of t ?? []) i.parallax && (r ??= /* @__PURE__ */ new Map()).set(i.id, e(n, i.parallax));
109
113
  if (r === null) return null;
110
114
  let i = r;
111
115
  return (e) => i.get(e) ?? null;
112
116
  }
113
- function g(e, t = {}) {
114
- let n = e, r = typeof e.getChildren == "function" && typeof e.getNode == "function", a = /* @__PURE__ */ new Map(), o = (t) => typeof e.getWorldPose == "function" ? e.getWorldPose(t) : e.getPose(t), s = typeof e.getNode == "function" ? i(e) : null, c = (e) => ({
115
- ...n.getNode(e),
116
- id: e,
117
- pose: o(e)
118
- });
119
- return {
120
- order() {
121
- if (!r) return a = /* @__PURE__ */ new Map(), e.getNodes().map((e) => ({
122
- ...e,
123
- id: e.id,
124
- pose: o(e.id)
125
- }));
126
- let t = [], i = /* @__PURE__ */ new Map(), s = (e, r) => {
127
- for (let a of n.getChildren(e)) {
128
- let e = c(a);
129
- r && i.set(a, r), t.push(e), s(a, e);
130
- }
131
- };
132
- return s(null, null), a = i, t;
133
- },
134
- ...t.alphaOf ? { alphaOf: t.alphaOf } : {},
135
- ...t.layerIsPainted ? { layerIsPainted: t.layerIsPainted } : {},
136
- ...t.planeOf ? { planeOf: t.planeOf } : {},
137
- poseOf: (e) => o(e.id),
138
- ...s ? { derivedPathOf: (e) => s(e.id) } : {},
139
- parentsOf(e) {
140
- let t = [], n = a.get(e.id), r = /* @__PURE__ */ new Set();
141
- for (; n && !r.has(n.id);) r.add(n.id), t.push(n), n = a.get(n.id);
142
- return t;
143
- }
144
- };
145
- }
146
117
  //#endregion
147
- export { g as adapterPickSource, p as hiddenLayerIds, u as ownClipOf, d as pickWalk, m as scenePickSource, h as scenePlaneOf };
118
+ export { l as adapterPickSource, h as hiddenLayerIds, f as ownClipOf, p as pickWalk, g as scenePickSource, _ as scenePlaneOf };
148
119
 
149
120
  //# sourceMappingURL=pickWalk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pickWalk.js","names":["EMPTY_PARENTS","ownClipOf","node","pose","findShapeSilhouette","derived","pickWalk","includeContainers","q","isLocked","src","out","clipPath","carry","clipCarrier","clipOf","cached","ancestor","resolved","planeQueries","queryFor","layer","found","map","query","clipped","clip","lockedNodeTest","locked","scene","lockedLayers","cur","asNodeId","id","seen","hiddenLayerIds","layers","scenePickSource","hidden","opts","faded","enumerable","alphaOf","a","readAlpha","paintedPoseOf","scenePaintedPoseOf","poseOf","getPose","childrenOf","depOf","dep","resolveDerivedPath","sceneDerivedPath","sceneDerivedPathOf","derivedPathOf","n","showsComputedPath","planeOf","scenePlaneOf","parentId","chain","parent","layerIsPainted","maps","l","planeMap","camera","adapterPickSource","hier","adapter","hierarchical","parents","worldPose","adapterDerivedPathOf","nodeOf","next","visit","childId","gates"],"sources":["../../src/canvas/pickWalk.ts"],"sourcesContent":["/**\n * The one hit-test walk. Everything that decides whether a node *can* be hit lives here; a\n * query supplies only the shape test and the clip predicate for its own region.\n *\n * The gates, in the order the walk applies them:\n * 1. containers, when the query does not want them\n * 2. the layer is painted at all — scene visibility, and the asking view's\n * `layerVisibility` / `layerOrder`\n * 3. painted alpha is above zero\n * 4. the node is not locked, unless the query asks for locked nodes\n * 5. the query's own shape test\n * 6. every ancestor clip admits the query region\n *\n * 2, 3 and 6 are all \"the renderer did not put this on screen\". A pick path\n * that skips one answers for a node the user cannot see. 4 is the other axis:\n * a locked node is on screen and still out of reach.\n */\n\nimport type { Path } from '@weasel-js/geom';\nimport { findShapeSilhouette } from 'canvas/NodeShape';\nimport { adapterDerivedPathOf, type DerivingAdapter } from './adapterDerivedPath';\nimport type { ClipFromPoseFn, DerivedDep, Node, NodeId, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport { resolveDerivedPath, sceneDerivedPathOf, scenePaintedPoseOf, showsComputedPath } from './derivedPath';\nimport { planeMap, type ParallaxOpts, type PlaneMap } from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport { clipCarrier } from './planeClips';\n\n/** Shared, never mutated: most scenes are flat and every node returns it. */\nconst EMPTY_PARENTS: readonly never[] = [];\n\n/** The subset of a node the walk itself reads. Deliberately structural: a\n * bare adapter's node satisfies it as readily as a `SceneNode`. */\nexport interface PickCandidate<TPose> {\n id: string;\n kind?: string;\n layer?: string;\n pose: TPose;\n /** `false` makes the node transparent to the walk — see `SceneNode.pickable`. */\n pickable?: boolean;\n clipFromPose?: ClipFromPoseFn<TPose>;\n}\n\n/**\n * Everything the walk reads that a **view** owns.\n *\n * A layer must not hold state a view owns, so none of these are closed over\n * at construction — each is asked per walk, of the view being dispatched to.\n */\nexport interface PickSource<TPose> {\n /** Candidates in paint order, back-to-front. Containers included; the\n * query decides whether they can be hit. */\n order(): readonly PickCandidate<TPose>[];\n /** The pose the renderer draws — override-aware. Not `node.pose`, which is\n * how the render and pick paths came to disagree about where a node is. */\n poseOf(node: PickCandidate<TPose>): TPose;\n /** Ancestors, innermost first. Only walked for candidates that already\n * passed their own shape test. */\n parentsOf(node: PickCandidate<TPose>): readonly PickCandidate<TPose>[];\n /** Painted alpha for the asking view: the view's `alphaFor` times any\n * per-node override alpha. Omit when the source has no alpha concept. */\n alphaOf?(id: string): number;\n /** Whether this layer reaches the screen in the asking view. Omit for a\n * source with no layers. */\n layerIsPainted?(layer: string): boolean;\n /** Whether the node is locked — painted, but not something a pointer can\n * take. Omit for a source with no lock concept. */\n isLocked?(node: PickCandidate<TPose>): boolean;\n /** The path a node computes from its dependencies, or null for none. */\n derivedPathOf?(node: PickCandidate<TPose>): Path | null;\n /** How the asking view's world maps into a parallax layer's, or null for a\n * layer that moves with the camera. Omit for a source with no planes. */\n planeOf?(layer: string): PlaneMap | null;\n}\n\n/** One hit-test question: what region, and what counts as covering it. */\nexport interface PickQuery<TPose> {\n /** Default `true`. The area walks exclude containers so a marquee does not\n * return a container and its children both. */\n includeContainers?: boolean;\n /** Default `false`. Every selecting or editing query passes over locked\n * nodes; one that only samples what is painted can take them back. */\n includeLocked?: boolean;\n /** Does this node, drawn at this pose, cover the query region? `derived`\n * is the node's resolved path when it has one — a derived node's pose is a\n * placeholder, so a region test that reads only the pose answers for the\n * wrong box. */\n hits(node: PickCandidate<TPose>, pose: TPose, derived?: Path | null): boolean;\n /**\n * Does an ancestor's clip leave anything of `node` for this query to hit?\n *\n * A point query asks point-in-clip and ignores the node. An area query has\n * to ask about the node as well: the clip and the area can overlap where\n * the node is not, and the node and the clip can overlap where the area is\n * not, and only the two terms together reject both.\n */\n clipAdmits(\n clip: Path,\n node: PickCandidate<TPose>,\n pose: TPose,\n derived?: Path | null,\n ): boolean;\n /** The same question asked in a parallax plane's world: the region carried\n * through `map`, and any screen-pixel slop re-derived at the plane's scale.\n * A query without it cannot reach nodes on a plane — it would test them\n * where their poses sit rather than where they are painted. */\n inPlane?(map: PlaneMap): PickQuery<TPose>;\n}\n\n/** The clip a container imposes on its subtree, or null when it imposes none. */\nexport function ownClipOf<TPose>(\n node: PickCandidate<TPose>,\n pose: TPose,\n derived?: Path | null,\n): Path | null {\n if (node.kind !== 'container') return null;\n if (typeof node.clipFromPose === 'function') return node.clipFromPose(pose);\n return findShapeSilhouette(\n node as unknown as Node<unknown, string, TPose>,\n pose,\n { derivedPath: derived },\n );\n}\n\n/**\n * Collect every candidate the query hits, back-to-front — the last element is\n * the topmost, which is the order `pickTopMostHit` expects.\n */\nexport function pickWalk<TPose>(\n src: PickSource<TPose>,\n q: PickQuery<TPose>,\n): string[] {\n const includeContainers = q.includeContainers ?? true;\n const isLocked = q.includeLocked === true ? undefined : src.isLocked;\n const out: string[] = [];\n\n // Resolving a container's clip is the expensive half, so the *path* is memoized per\n // container for the walk. The predicate re-runs per candidate: caching its answer per\n // container would answer the wrong question for an area query.\n const clipPath = new Map<string, Path | null>();\n // A clip is in its container's plane; the query is in the candidate's.\n const carry = clipCarrier(src.planeOf ?? null);\n\n const clipOf = (ancestor: PickCandidate<TPose>): Path | null => {\n const cached = clipPath.get(ancestor.id);\n if (cached !== undefined) return cached;\n const resolved = ownClipOf(\n ancestor, src.poseOf(ancestor), src.derivedPathOf?.(ancestor),\n );\n clipPath.set(ancestor.id, resolved);\n return resolved;\n };\n\n // One reprojected query per plane per walk; `null` marks a plane this\n // query cannot reach.\n const planeQueries = new Map<string, PickQuery<TPose> | null>();\n const queryFor = (layer: string | undefined): PickQuery<TPose> | null => {\n if (layer === undefined || src.planeOf === undefined) return q;\n let found = planeQueries.get(layer);\n if (found === undefined) {\n const map = src.planeOf(layer);\n found = map === null ? q : (q.inPlane?.(map) ?? null);\n planeQueries.set(layer, found);\n }\n return found;\n };\n\n for (const node of src.order()) {\n if (!includeContainers && node.kind === 'container') continue;\n // Transparent to picking: the click belongs to whatever is behind it,\n // which for a label inside a box is the box.\n if (node.pickable === false) continue;\n if (node.layer !== undefined && src.layerIsPainted?.(node.layer) === false) continue;\n if (src.alphaOf !== undefined && src.alphaOf(node.id) <= 0) continue;\n if (isLocked !== undefined && isLocked(node)) continue;\n\n const query = queryFor(node.layer);\n if (query === null) continue;\n const pose = src.poseOf(node);\n const derived = src.derivedPathOf?.(node);\n if (!query.hits(node, pose, derived)) continue;\n\n let clipped = false;\n for (const ancestor of src.parentsOf(node)) {\n const clip = clipOf(ancestor);\n if (clip === null) continue;\n if (!query.clipAdmits(carry(clip, ancestor.layer, node.layer), node, pose, derived)) {\n clipped = true;\n break;\n }\n }\n if (clipped) continue;\n\n out.push(node.id);\n }\n\n return out;\n}\n\n/** Answers `Scene.isLocked` from the layer records and parent links alone,\n * so a partial scene stand-in works too. Null when nothing is locked, which\n * is what keeps the gate off the walk in the common case. */\nfunction lockedNodeTest(\n scene: Pick<Scene<unknown, string, unknown>, 'layers' | 'get'>,\n): ((id: string) => boolean) | null {\n let locked: Set<string> | null = null;\n for (const layer of scene.layers ?? []) {\n if (layer.locked === true) (locked ??= new Set()).add(layer.id);\n }\n if (locked === null) return null;\n const lockedLayers = locked;\n return (id) => {\n let cur = scene.get(asNodeId(id));\n const seen = new Set<string>();\n while (cur !== undefined && !seen.has(cur.id)) {\n if (lockedLayers.has(cur.layer)) return true;\n seen.add(cur.id);\n cur = cur.parent === null ? undefined : scene.get(cur.parent);\n }\n return false;\n };\n}\n\n/** Layer ids the scene reports as hidden. Only an explicit `false` hides a\n * layer: a partial scene stand-in that omits the flag stays pickable. */\nexport function hiddenLayerIds(\n layers: readonly { id: string; visible?: boolean }[] | undefined,\n): Set<string> {\n const out = new Set<string>();\n for (const layer of layers ?? []) {\n if (layer.visible === false) out.add(layer.id);\n }\n return out;\n}\n\n/**\n * The two answers a pick needs from the view it is asked for rather than from\n * the data behind it: how that view paints a node, and whether it paints a\n * layer at all. A scene and a bare adapter take the same pair.\n */\nexport interface ViewPickGates {\n /** Painted alpha: the view's `alphaFor` times any per-node override alpha.\n * A node painted at alpha 0 cannot be hit. */\n alphaOf?: (id: string) => number;\n /** Whether a node's `layer` reaches the screen in the asking view. */\n layerIsPainted?: (layer: string) => boolean;\n}\n\n/** The gates a bare adapter takes from its view, plus how that view's camera\n * maps into each parallax layer — see `scenePlaneOf`. */\nexport interface AdapterPickGates extends ViewPickGates {\n planeOf?: (layer: string) => PlaneMap | null;\n}\n\nexport interface ScenePickSourceOptions<TPose> extends ViewPickGates {\n /** Pose lookup, when the caller holds an adapter that already resolves\n * overrides. Defaults to `effectivePose` against the scene's own. */\n getPose?: (id: string) => TPose;\n /** The asking view's composed alpha — `alphaFor(id)` times override alpha.\n * Defaults to the override alpha alone, which is all a bare scene knows. */\n alphaOf?: (id: string) => number;\n /** The asking view's answer to \"does this scene layer reach the screen\",\n * which is `layerVisibility` and `layerOrder` on top of the scene's own\n * `visible` flag. Consulted after the scene's flag, never instead of it. */\n layerIsPainted?: (layer: string) => boolean;\n /** The asking view's camera. With it, a layer carrying `parallax` is picked\n * through its plane; without it, every layer is taken to move with the\n * camera. */\n camera?: View;\n}\n\nexport function scenePickSource<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n opts: ScenePickSourceOptions<TPose> = {},\n): PickSource<TPose> {\n const hidden = hiddenLayerIds(scene.layers);\n const locked = lockedNodeTest(scene as never);\n const { getPose, alphaOf, layerIsPainted } = opts;\n\n // Resolved once per walk rather than once per candidate. Needs enumeration — a\n // partial scene stand-in carrying only `read` falls back to reading per node.\n let faded: Set<string> | null = null;\n const enumerable = typeof scene.overrides?.ids === 'function';\n if (!alphaOf && enumerable) {\n for (const id of scene.overrides.ids()) {\n const a = scene.overrides.read(id)?.alpha;\n if (a !== undefined && a <= 0) (faded ??= new Set()).add(id);\n }\n }\n const readAlpha = alphaOf\n ?? (enumerable\n ? (faded ? (id: string) => (faded.has(id) ? 0 : 1) : undefined)\n : (id: string) => scene.overrides.read(asNodeId(id))?.alpha ?? 1);\n\n // A composing strategy makes a node's own pose local, so picking folds the\n // parent chain the same way the render walk does: one definition of both.\n const paintedPoseOf = scenePaintedPoseOf(scene);\n const poseOf = getPose\n ? (node: PickCandidate<TPose>) => getPose(node.id)\n : (node: PickCandidate<TPose>) => paintedPoseOf(node as never);\n\n // Through `poseOf`, not the document pose: a derived node has to be tested\n // where the renderer draws its dependencies, which is what an override says.\n const childrenOf = (id: NodeId): readonly NodeId[] => scene.childrenOf(id);\n const depOf = (id: NodeId): DerivedDep<TPose> | undefined => {\n const dep = scene.get(id);\n if (dep === undefined) return undefined;\n return {\n node: dep as Node<unknown, string, TPose>,\n pose: poseOf(dep as never),\n get path(): Path | null {\n return resolveDerivedPath(dep as never, depOf, childrenOf);\n },\n };\n };\n\n const sceneDerivedPath = getPose ? null : sceneDerivedPathOf(scene);\n const derivedPathOf = (node: PickCandidate<TPose>): Path | null => {\n const n = node as unknown as Node<TData, TLayer, TPose>;\n if (!sceneDerivedPath) return n.dependsOn === undefined ? null : resolveDerivedPath(n, depOf, childrenOf);\n return showsComputedPath(scene, n) ? sceneDerivedPath(n) : null;\n };\n\n const planeOf = opts.camera ? scenePlaneOf(scene.layers, opts.camera) : null;\n\n return {\n ...(planeOf ? { planeOf } : {}),\n order: () => scene.renderOrderNodes() as unknown as readonly PickCandidate<TPose>[],\n derivedPathOf,\n poseOf,\n parentsOf(node) {\n let parentId = (node as { parent?: string | null }).parent ?? null;\n if (parentId === null) return EMPTY_PARENTS;\n const chain: PickCandidate<TPose>[] = [];\n const seen = new Set<string>();\n while (parentId !== null) {\n if (seen.has(parentId)) break;\n seen.add(parentId);\n const parent = scene.get(asNodeId(parentId));\n if (!parent) break;\n chain.push(parent as unknown as PickCandidate<TPose>);\n parentId = parent.parent ?? null;\n }\n return chain;\n },\n // Absent entirely when nothing is faded, so the walk skips the gate.\n ...(readAlpha ? { alphaOf: readAlpha } : {}),\n ...(locked ? { isLocked: (node: PickCandidate<TPose>) => locked(node.id) } : {}),\n ...(hidden.size > 0 || layerIsPainted\n ? {\n layerIsPainted: (layer: string) =>\n !hidden.has(layer) && (layerIsPainted === undefined || layerIsPainted(layer)),\n }\n : {}),\n };\n}\n\n/** Each parallax layer's plane map under `camera`, or null when no layer is a\n * plane — which keeps the per-layer lookup off the walk entirely. */\nexport function scenePlaneOf(\n layers: readonly { id: string; parallax?: ParallaxOpts }[] | undefined,\n camera: View,\n): ((layer: string) => PlaneMap | null) | null {\n let maps: Map<string, PlaneMap> | null = null;\n for (const l of layers ?? []) {\n if (l.parallax) (maps ??= new Map()).set(l.id, planeMap(camera, l.parallax));\n }\n if (maps === null) return null;\n const found = maps;\n return (layer) => found.get(layer) ?? null;\n}\n\n/** The adapter surface the walk can reach without a `Scene`. */\ninterface PickAdapter<TPose> {\n /** Composed world pose, when the adapter has a composition strategy.\n * Falls back to `getPose`, which is the same value under the\n * absolute-pose model. */\n getWorldPose?(id: string): TPose;\n getNodes(): readonly { id: string }[];\n getPose(id: string): TPose;\n getNode?: (id: string) => unknown;\n getChildren?: (parentId: string | null) => readonly string[];\n}\n\n/**\n * A source over a bare `SelectAdapter`, for consumers with no `Scene`.\n *\n * A hierarchical adapter is walked depth-first, parents before children —\n * the same back-to-front order `renderOrderNodes` produces for a single\n * layer. A flat adapter falls back to `getNodes()`, which carries no\n * parentage, so nothing clips.\n *\n * `gates` come from whichever view is picking, never from the adapter.\n */\nexport function adapterPickSource<TPose>(\n adapter: PickAdapter<TPose>,\n gates: AdapterPickGates = {},\n): PickSource<TPose> {\n const hier = adapter as Required<Pick<PickAdapter<TPose>, 'getNode' | 'getChildren'>>;\n const hierarchical =\n typeof adapter.getChildren === 'function' && typeof adapter.getNode === 'function';\n\n // Rebuilt per walk: the tree may have changed between queries, and a walk\n // is the only thing that reads it.\n let parents = new Map<string, PickCandidate<TPose>>();\n\n // The adapter composes if it has a strategy; `getPose` alone is the node's\n // own pose, which is not where a framed child is drawn.\n const worldPose = (id: string): TPose =>\n (typeof adapter.getWorldPose === 'function' ? adapter.getWorldPose(id) : adapter.getPose(id));\n\n const derived = typeof adapter.getNode === 'function' ? adapterDerivedPathOf(adapter as DerivingAdapter<TPose>) : null;\n const nodeOf = (id: string): PickCandidate<TPose> => {\n const raw = hier.getNode(id) as Partial<PickCandidate<TPose>>;\n return { ...raw, id, pose: worldPose(id) } as PickCandidate<TPose>;\n };\n\n return {\n order() {\n if (!hierarchical) {\n parents = new Map();\n return adapter.getNodes().map((n) => ({\n ...(n as object), id: n.id, pose: worldPose(n.id),\n })) as PickCandidate<TPose>[];\n }\n const out: PickCandidate<TPose>[] = [];\n const next = new Map<string, PickCandidate<TPose>>();\n const visit = (parentId: string | null, parent: PickCandidate<TPose> | null): void => {\n for (const childId of hier.getChildren(parentId)) {\n const node = nodeOf(childId);\n if (parent) next.set(childId, parent);\n out.push(node);\n visit(childId, node);\n }\n };\n visit(null, null);\n parents = next;\n return out;\n },\n ...(gates.alphaOf ? { alphaOf: gates.alphaOf } : {}),\n ...(gates.layerIsPainted ? { layerIsPainted: gates.layerIsPainted } : {}),\n ...(gates.planeOf ? { planeOf: gates.planeOf } : {}),\n poseOf: (node) => worldPose(node.id),\n ...(derived ? { derivedPathOf: (node: PickCandidate<TPose>) => derived(node.id) } : {}),\n parentsOf(node) {\n const chain: PickCandidate<TPose>[] = [];\n let cur = parents.get(node.id);\n const seen = new Set<string>();\n while (cur && !seen.has(cur.id)) {\n seen.add(cur.id);\n chain.push(cur);\n cur = parents.get(cur.id);\n }\n return chain;\n },\n };\n}\n"],"mappings":";;;;;;;;AA6BA,IAAMA,IAAkC,CAAC;AAiFzC,SAAgBC,EACd,GACA,GACA,GACa;CAGb,OAFIC,EAAK,SAAS,cACd,OAAOA,EAAK,gBAAiB,aAAmBA,EAAK,aAAaC,CAAI,IACnEC,EACLF,GACAC,GACA,EAAE,aAAaE,EAAQ,CACzB,IANsC;AAOxC;AAMA,SAAgBC,EACd,GACA,GACU;CACV,IAAMC,IAAoBC,EAAE,qBAAqB,IAC3CC,IAAWD,EAAE,kBAAkB,KAAO,KAAA,IAAYE,EAAI,UACtDC,IAAgB,CAAC,GAKjBC,oBAAW,IAAI,IAAyB,GAExCC,IAAQC,EAAYJ,EAAI,WAAW,IAAI,GAEvCK,KAAU,MAAgD;EAC9D,IAAMC,IAASJ,EAAS,IAAIK,EAAS,EAAE;EACvC,IAAID,MAAW,KAAA,GAAW,OAAOA;EACjC,IAAME,IAAWjB,EACfgB,GAAUP,EAAI,OAAOO,CAAQ,GAAGP,EAAI,gBAAgBO,CAAQ,CAC9D;EAEA,OADAL,EAAS,IAAIK,EAAS,IAAIC,CAAQ,GAC3BA;CACT,GAIMC,oBAAe,IAAI,IAAqC,GACxDC,KAAY,MAAuD;EACvE,IAAIC,MAAU,KAAA,KAAaX,EAAI,YAAY,KAAA,GAAW,OAAOF;EAC7D,IAAIc,IAAQH,EAAa,IAAIE,CAAK;EAClC,IAAIC,MAAU,KAAA,GAAW;GACvB,IAAMC,IAAMb,EAAI,QAAQW,CAAK;GAE7B,AADA,IAAQE,MAAQ,OAAOf,IAAKA,EAAE,UAAUe,CAAG,KAAK,MAChDJ,EAAa,IAAIE,GAAOC,CAAK;EAC/B;EACA,OAAOA;CACT;CAEA,KAAK,IAAMpB,KAAQQ,EAAI,MAAM,GAAG;EAO9B,IANI,CAACH,KAAqBL,EAAK,SAAS,eAGpCA,EAAK,aAAa,MAClBA,EAAK,UAAU,KAAA,KAAaQ,EAAI,iBAAiBR,EAAK,KAAK,MAAM,MACjEQ,EAAI,YAAY,KAAA,KAAaA,EAAI,QAAQR,EAAK,EAAE,KAAK,KACrDO,MAAa,KAAA,KAAaA,EAASP,CAAI,GAAG;EAE9C,IAAMsB,IAAQJ,EAASlB,EAAK,KAAK;EACjC,IAAIsB,MAAU,MAAM;EACpB,IAAMrB,IAAOO,EAAI,OAAOR,CAAI,GACtBG,IAAUK,EAAI,gBAAgBR,CAAI;EACxC,IAAI,CAACsB,EAAM,KAAKtB,GAAMC,GAAME,CAAO,GAAG;EAEtC,IAAIoB,IAAU;EACd,KAAK,IAAMR,KAAYP,EAAI,UAAUR,CAAI,GAAG;GAC1C,IAAMwB,IAAOX,EAAOE,CAAQ;GAC5B,IAAIS,MAAS,QACT,CAACF,EAAM,WAAWX,EAAMa,GAAMT,EAAS,OAAOf,EAAK,KAAK,GAAGA,GAAMC,GAAME,CAAO,GAAG;IACnF,IAAU;IACV;GACF;EACF;EACA,AAAIoB,KAEJd,EAAI,KAAKT,EAAK,EAAE;CAClB;CAEA,OAAOS;AACT;AAKA,SAASgB,EACP,GACkC;CAClC,IAAIC,IAA6B;CACjC,KAAK,IAAMP,KAASQ,EAAM,UAAU,CAAC,GACnC,AAAIR,EAAM,WAAW,OAAO,sBAAW,IAAI,IAAI,EAAA,CAAG,IAAIA,EAAM,EAAE;CAEhE,IAAIO,MAAW,MAAM,OAAO;CAC5B,IAAME,IAAeF;CACrB,QAAQ,MAAO;EACb,IAAIG,IAAMF,EAAM,IAAIG,EAASC,CAAE,CAAC,GAC1BC,oBAAO,IAAI,IAAY;EAC7B,OAAOH,MAAQ,KAAA,KAAa,CAACG,EAAK,IAAIH,EAAI,EAAE,IAAG;GAC7C,IAAID,EAAa,IAAIC,EAAI,KAAK,GAAG,OAAO;GAExC,AADAG,EAAK,IAAIH,EAAI,EAAE,GACf,IAAMA,EAAI,WAAW,OAAO,KAAA,IAAYF,EAAM,IAAIE,EAAI,MAAM;EAC9D;EACA,OAAO;CACT;AACF;AAIA,SAAgBI,EACd,GACa;CACb,IAAMxB,oBAAM,IAAI,IAAY;CAC5B,KAAK,IAAMU,KAASe,KAAU,CAAC,GAC7B,AAAIf,EAAM,YAAY,MAAOV,EAAI,IAAIU,EAAM,EAAE;CAE/C,OAAOV;AACT;AAsCA,SAAgB0B,EACd,GACA,IAAsC,CAAC,GACpB;CACnB,IAAMC,IAASH,EAAeN,EAAM,MAAM,GACpCD,IAASD,EAAeE,CAAc,GACtC,EAAE,YAAS,YAAS,sBAAmBU,GAIzCC,IAA4B,MAC1BC,IAAa,OAAOZ,EAAM,WAAW,OAAQ;CACnD,IAAI,CAACa,KAAWD,GACd,KAAK,IAAMR,KAAMJ,EAAM,UAAU,IAAI,GAAG;EACtC,IAAMc,IAAId,EAAM,UAAU,KAAKI,CAAE,CAAC,EAAE;EACpC,AAAIU,MAAM,KAAA,KAAaA,KAAK,MAAI,sBAAU,IAAI,IAAI,EAAA,CAAG,IAAIV,CAAE;CAC7D;CAEF,IAAMW,IAAYF,MACZD,IACCD,KAAS,MAAgB,IAAM,IAAIP,CAAE,IAAa,KAAA,KAClD,MAAeJ,EAAM,UAAU,KAAKG,EAASC,CAAE,CAAC,CAAC,EAAE,SAAS,IAI7DY,IAAgBC,EAAmBjB,CAAK,GACxCkB,IAASC,KACV,MAA+BA,EAAQ9C,EAAK,EAAE,KAC9C,MAA+B2C,EAAc3C,CAAa,GAIzD+C,KAAc,MAAkCpB,EAAM,WAAWI,CAAE,GACnEiB,KAAS,MAA8C;EAC3D,IAAMC,IAAMtB,EAAM,IAAII,CAAE;EACxB,IAAIkB,MAAQ,KAAA,GACZ,OAAO;GACL,MAAMA;GACN,MAAMJ,EAAOI,CAAY;GACzB,IAAI,OAAoB;IACtB,OAAOC,EAAmBD,GAAcD,GAAOD,CAAU;GAC3D;EACF;CACF,GAEMI,IAAmBL,IAAU,OAAOM,EAAmBzB,CAAK,GAC5D0B,KAAiB,MAA4C;EACjE,IAAMC,IAAItD;EAEV,OADKmD,IACEI,EAAkB5B,GAAO2B,CAAC,IAAIH,EAAiBG,CAAC,IAAI,OAD7BA,EAAE,cAAc,KAAA,IAAY,OAAOJ,EAAmBI,GAAGN,GAAOD,CAAU;CAE1G,GAEMS,IAAUnB,EAAK,SAASoB,EAAa9B,EAAM,QAAQU,EAAK,MAAM,IAAI;CAExE,OAAO;EACL,GAAImB,IAAU,EAAE,WAAQ,IAAI,CAAC;EAC7B,aAAa7B,EAAM,iBAAiB;EACpC;EACA;EACA,UAAU,GAAM;GACd,IAAI+B,IAAY1D,EAAoC,UAAU;GAC9D,IAAI0D,MAAa,MAAM,OAAO5D;GAC9B,IAAM6D,IAAgC,CAAC,GACjC3B,oBAAO,IAAI,IAAY;GAC7B,OAAO0B,MAAa,QACd,GAAK,IAAIA,CAAQ,IADG;IAExB,EAAK,IAAIA,CAAQ;IACjB,IAAME,IAASjC,EAAM,IAAIG,EAAS4B,CAAQ,CAAC;IAC3C,IAAI,CAACE,GAAQ;IAEb,AADAD,EAAM,KAAKC,CAAyC,GACpD,IAAWA,EAAO,UAAU;GAC9B;GACA,OAAOD;EACT;EAEA,GAAIjB,IAAY,EAAE,SAASA,EAAU,IAAI,CAAC;EAC1C,GAAIhB,IAAS,EAAE,WAAW,MAA+BA,EAAO1B,EAAK,EAAE,EAAE,IAAI,CAAC;EAC9E,GAAIoC,EAAO,OAAO,KAAKyB,IACnB,EACA,iBAAiB,MACf,CAACzB,EAAO,IAAIjB,CAAK,MAAM0C,MAAmB,KAAA,KAAaA,EAAe1C,CAAK,GAC/E,IACE,CAAC;CACP;AACF;AAIA,SAAgBsC,EACd,GACA,GAC6C;CAC7C,IAAIK,IAAqC;CACzC,KAAK,IAAMC,KAAK7B,KAAU,CAAC,GACzB,AAAI6B,EAAE,aAAW,sBAAS,IAAI,IAAI,EAAA,CAAG,IAAIA,EAAE,IAAIC,EAASC,GAAQF,EAAE,QAAQ,CAAC;CAE7E,IAAID,MAAS,MAAM,OAAO;CAC1B,IAAM1C,IAAQ0C;CACd,QAAQ,MAAU1C,EAAM,IAAID,CAAK,KAAK;AACxC;AAwBA,SAAgB+C,EACd,GACA,IAA0B,CAAC,GACR;CACnB,IAAMC,IAAOC,GACPC,IACJ,OAAOD,EAAQ,eAAgB,cAAc,OAAOA,EAAQ,WAAY,YAItEE,oBAAU,IAAI,IAAkC,GAI9CC,KAAa,MAChB,OAAOH,EAAQ,gBAAiB,aAAaA,EAAQ,aAAarC,CAAE,IAAIqC,EAAQ,QAAQrC,CAAE,GAEvF5B,IAAU,OAAOiE,EAAQ,WAAY,aAAaI,EAAqBJ,CAAiC,IAAI,MAC5GK,KAAU,OAEP;EAAE,GADGN,EAAK,QAAQpC,CACb;EAAK;EAAI,MAAMwC,EAAUxC,CAAE;CAAE;CAG3C,OAAO;EACL,QAAQ;GACN,IAAI,CAACsC,GAEH,OADA,oBAAU,IAAI,IAAI,GACXD,EAAQ,SAAS,CAAC,CAAC,KAAK,OAAO;IACpC,GAAId;IAAc,IAAIA,EAAE;IAAI,MAAMiB,EAAUjB,EAAE,EAAE;GAClD,EAAE;GAEJ,IAAM7C,IAA8B,CAAC,GAC/BiE,oBAAO,IAAI,IAAkC,GAC7CC,KAAS,GAAyB,MAA8C;IACpF,KAAK,IAAMC,KAAWT,EAAK,YAAYT,CAAQ,GAAG;KAChD,IAAM1D,IAAOyE,EAAOG,CAAO;KAG3B,AAFIhB,KAAQc,EAAK,IAAIE,GAAShB,CAAM,GACpCnD,EAAI,KAAKT,CAAI,GACb2E,EAAMC,GAAS5E,CAAI;IACrB;GACF;GAGA,OAFA2E,EAAM,MAAM,IAAI,GAChB,IAAUD,GACHjE;EACT;EACA,GAAIoE,EAAM,UAAU,EAAE,SAASA,EAAM,QAAQ,IAAI,CAAC;EAClD,GAAIA,EAAM,iBAAiB,EAAE,gBAAgBA,EAAM,eAAe,IAAI,CAAC;EACvE,GAAIA,EAAM,UAAU,EAAE,SAASA,EAAM,QAAQ,IAAI,CAAC;EAClD,SAAS,MAASN,EAAUvE,EAAK,EAAE;EACnC,GAAIG,IAAU,EAAE,gBAAgB,MAA+BA,EAAQH,EAAK,EAAE,EAAE,IAAI,CAAC;EACrF,UAAU,GAAM;GACd,IAAM2D,IAAgC,CAAC,GACnC9B,IAAMyC,EAAQ,IAAItE,EAAK,EAAE,GACvBgC,oBAAO,IAAI,IAAY;GAC7B,OAAOH,KAAO,CAACG,EAAK,IAAIH,EAAI,EAAE,IAG5B,AAFAG,EAAK,IAAIH,EAAI,EAAE,GACf8B,EAAM,KAAK9B,CAAG,GACd,IAAMyC,EAAQ,IAAIzC,EAAI,EAAE;GAE1B,OAAO8B;EACT;CACF;AACF"}
1
+ {"version":3,"file":"pickWalk.js","names":["EMPTY_PARENTS","ownClipOf","node","pose","findShapeSilhouette","derived","pickWalk","includeContainers","q","isLocked","src","out","clipPath","carry","clipCarrier","clipOf","cached","ancestor","resolved","copyMaps","copiesOf","found","fn","invert","m","planeQueries","queryFor","layer","map","order","copying","n","query","reaches","lockedNodeTest","locked","scene","lockedLayers","cur","asNodeId","id","seen","hiddenLayerIds","layers","scenePickSource","hidden","opts","faded","enumerable","alphaOf","a","readAlpha","paintedPoseOf","scenePaintedPoseOf","poseOf","getPose","childrenOf","depOf","dep","resolveDerivedPath","sceneDerivedPath","sceneDerivedPathOf","derivedPathOf","showsComputedPath","planeOf","scenePlaneOf","parentId","chain","parent","layerIsPainted","maps","l","planeMap","camera","adapterPickSource"],"sources":["../../src/canvas/pickWalk.ts"],"sourcesContent":["/**\n * The one hit-test walk. Everything that decides whether a node *can* be hit lives here; a\n * query supplies only the shape test and the clip predicate for its own region.\n *\n * The gates, in the order the walk applies them:\n * 1. containers, when the query does not want them\n * 2. the layer is painted at all — scene visibility, and the asking view's\n * `layerVisibility` / `layerOrder`\n * 3. painted alpha is above zero\n * 4. the node is not locked, unless the query asks for locked nodes\n * 5. the query's own shape test\n * 6. every ancestor clip admits the query region\n *\n * 2, 3 and 6 are all \"the renderer did not put this on screen\". A pick path\n * that skips one answers for a node the user cannot see. 4 is the other axis:\n * a locked node is on screen and still out of reach.\n */\n\nimport { invert, type Affine, type Path } from '@weasel-js/geom';\nimport { findShapeSilhouette } from 'canvas/NodeShape';\nimport type { ClipFromPoseFn, CopiesFromPoseFn, DerivedDep, Node, NodeId, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport { resolveDerivedPath, sceneDerivedPathOf, scenePaintedPoseOf, showsComputedPath } from './derivedPath';\nimport { planeMap, type ParallaxOpts, type PlaneMap } from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport { clipCarrier } from './planeClips';\nimport { reaches } from './pickReach';\n\n/** Shared, never mutated: most scenes are flat and every node returns it. */\nconst EMPTY_PARENTS: readonly never[] = [];\n\n/** The subset of a node the walk itself reads. Deliberately structural: a\n * bare adapter's node satisfies it as readily as a `SceneNode`. */\nexport interface PickCandidate<TPose> {\n id: string;\n kind?: string;\n layer?: string;\n pose: TPose;\n /** `false` makes the node transparent to the walk — see `SceneNode.pickable`. */\n pickable?: boolean;\n clipFromPose?: ClipFromPoseFn<TPose>;\n copiesFromPose?: CopiesFromPoseFn<TPose>;\n}\n\n/**\n * Everything the walk reads that a **view** owns.\n *\n * A layer must not hold state a view owns, so none of these are closed over\n * at construction — each is asked per walk, of the view being dispatched to.\n */\nexport interface PickSource<TPose> {\n /** Candidates in paint order, back-to-front. Containers included; the\n * query decides whether they can be hit. */\n order(): readonly PickCandidate<TPose>[];\n /** The pose the renderer draws — override-aware. Not `node.pose`, which is\n * how the render and pick paths came to disagree about where a node is. */\n poseOf(node: PickCandidate<TPose>): TPose;\n /** Ancestors, innermost first. Only walked for candidates that already\n * passed their own shape test. */\n parentsOf(node: PickCandidate<TPose>): readonly PickCandidate<TPose>[];\n /** Painted alpha for the asking view: the view's `alphaFor` times any\n * per-node override alpha. Omit when the source has no alpha concept. */\n alphaOf?(id: string): number;\n /** Whether this layer reaches the screen in the asking view. Omit for a\n * source with no layers. */\n layerIsPainted?(layer: string): boolean;\n /** Whether the node is locked — painted, but not something a pointer can\n * take. Omit for a source with no lock concept. */\n isLocked?(node: PickCandidate<TPose>): boolean;\n /** The path a node computes from its dependencies, or null for none. */\n derivedPathOf?(node: PickCandidate<TPose>): Path | null;\n /** How the asking view's world maps into a parallax layer's, or null for a\n * layer that moves with the camera. Omit for a source with no planes. */\n planeOf?(layer: string): PlaneMap | null;\n}\n\n/** One hit-test question: what region, and what counts as covering it. */\nexport interface PickQuery<TPose> {\n /** Default `true`. The area walks exclude containers so a marquee does not\n * return a container and its children both. */\n includeContainers?: boolean;\n /** Default `false`. Every selecting or editing query passes over locked\n * nodes; one that only samples what is painted can take them back. */\n includeLocked?: boolean;\n /** Does this node, drawn at this pose, cover the query region? `derived`\n * is the node's resolved path when it has one — a derived node's pose is a\n * placeholder, so a region test that reads only the pose answers for the\n * wrong box. */\n hits(node: PickCandidate<TPose>, pose: TPose, derived?: Path | null): boolean;\n /**\n * Does an ancestor's clip leave anything of `node` for this query to hit?\n *\n * A point query asks point-in-clip and ignores the node. An area query has\n * to ask about the node as well: the clip and the area can overlap where\n * the node is not, and the node and the clip can overlap where the area is\n * not, and only the two terms together reject both.\n */\n clipAdmits(\n clip: Path,\n node: PickCandidate<TPose>,\n pose: TPose,\n derived?: Path | null,\n ): boolean;\n /** The same question asked in a parallax plane's world: the region carried\n * through `map`, and any screen-pixel slop re-derived at the plane's scale.\n * A query without it cannot reach nodes on a plane — it would test them\n * where their poses sit rather than where they are painted. */\n inPlane?(map: PlaneMap): PickQuery<TPose>;\n /** The same question carried by `m`, an affine from world into the source\n * frame of a copy a container draws. A query without it cannot reach\n * copies — see `ContainerNode.copiesFromPose`. */\n inCopy?(m: Affine): PickQuery<TPose>;\n}\n\n/** The clip a container imposes on its subtree, or null when it imposes none. */\nexport function ownClipOf<TPose>(\n node: PickCandidate<TPose>,\n pose: TPose,\n derived?: Path | null,\n): Path | null {\n if (node.kind !== 'container') return null;\n if (typeof node.clipFromPose === 'function') return node.clipFromPose(pose);\n return findShapeSilhouette(\n node as unknown as Node<unknown, string, TPose>,\n pose,\n { derivedPath: derived },\n );\n}\n\n/**\n * Collect every candidate the query hits, back-to-front — the last element is\n * the topmost, which is the order `pickTopMostHit` expects.\n */\nexport function pickWalk<TPose>(\n src: PickSource<TPose>,\n q: PickQuery<TPose>,\n): string[] {\n const includeContainers = q.includeContainers ?? true;\n const isLocked = q.includeLocked === true ? undefined : src.isLocked;\n const out: string[] = [];\n\n // Resolving a container's clip is the expensive half, so the *path* is memoized per\n // container for the walk. The predicate re-runs per candidate: caching its answer per\n // container would answer the wrong question for an area query.\n const clipPath = new Map<string, Path | null>();\n // A clip is in its container's plane; the query is in the candidate's.\n const carry = clipCarrier(src.planeOf ?? null);\n\n const clipOf = (ancestor: PickCandidate<TPose>): Path | null => {\n const cached = clipPath.get(ancestor.id);\n if (cached !== undefined) return cached;\n const resolved = ownClipOf(\n ancestor, src.poseOf(ancestor), src.derivedPathOf?.(ancestor),\n );\n clipPath.set(ancestor.id, resolved);\n return resolved;\n };\n\n const copyMaps = new Map<string, readonly Affine[]>();\n const copiesOf = (ancestor: PickCandidate<TPose>): readonly Affine[] => {\n let found = copyMaps.get(ancestor.id);\n if (found === undefined) {\n const fn = ancestor.kind === 'container' ? ancestor.copiesFromPose : undefined;\n const copies = fn ? fn(src.poseOf(ancestor), ancestor as never) ?? [] : [];\n found = copies.map(invert).filter((m): m is Affine => m !== null);\n copyMaps.set(ancestor.id, found);\n }\n return found;\n };\n\n // One reprojected query per plane per walk; `null` marks a plane this\n // query cannot reach.\n const planeQueries = new Map<string, PickQuery<TPose> | null>();\n const queryFor = (layer: string | undefined): PickQuery<TPose> | null => {\n if (layer === undefined || src.planeOf === undefined) return q;\n let found = planeQueries.get(layer);\n if (found === undefined) {\n const map = src.planeOf(layer);\n found = map === null ? q : (q.inPlane?.(map) ?? null);\n planeQueries.set(layer, found);\n }\n return found;\n };\n\n const order = src.order();\n const copying = order.some((n) => n.kind === 'container' && typeof n.copiesFromPose === 'function');\n for (const node of order) {\n if (!includeContainers && node.kind === 'container') continue;\n // Transparent to picking: the click belongs to whatever is behind it,\n // which for a label inside a box is the box.\n if (node.pickable === false) continue;\n if (node.layer !== undefined && src.layerIsPainted?.(node.layer) === false) continue;\n if (src.alphaOf !== undefined && src.alphaOf(node.id) <= 0) continue;\n if (isLocked !== undefined && isLocked(node)) continue;\n\n const query = queryFor(node.layer);\n if (query === null) continue;\n const pose = src.poseOf(node);\n const derived = src.derivedPathOf?.(node);\n if (!reaches(node, pose, derived, query, () => src.parentsOf(node), copying, { clipOf, copiesOf, carry })) continue;\n out.push(node.id);\n }\n\n return out;\n}\n\n/** Answers `Scene.isLocked` from the layer records and parent links alone,\n * so a partial scene stand-in works too. Null when nothing is locked, which\n * is what keeps the gate off the walk in the common case. */\nfunction lockedNodeTest(\n scene: Pick<Scene<unknown, string, unknown>, 'layers' | 'get'>,\n): ((id: string) => boolean) | null {\n let locked: Set<string> | null = null;\n for (const layer of scene.layers ?? []) {\n if (layer.locked === true) (locked ??= new Set()).add(layer.id);\n }\n if (locked === null) return null;\n const lockedLayers = locked;\n return (id) => {\n let cur = scene.get(asNodeId(id));\n const seen = new Set<string>();\n while (cur !== undefined && !seen.has(cur.id)) {\n if (lockedLayers.has(cur.layer)) return true;\n seen.add(cur.id);\n cur = cur.parent === null ? undefined : scene.get(cur.parent);\n }\n return false;\n };\n}\n\n/** Layer ids the scene reports as hidden. Only an explicit `false` hides a\n * layer: a partial scene stand-in that omits the flag stays pickable. */\nexport function hiddenLayerIds(\n layers: readonly { id: string; visible?: boolean }[] | undefined,\n): Set<string> {\n const out = new Set<string>();\n for (const layer of layers ?? []) {\n if (layer.visible === false) out.add(layer.id);\n }\n return out;\n}\n\n/**\n * The two answers a pick needs from the view it is asked for rather than from\n * the data behind it: how that view paints a node, and whether it paints a\n * layer at all. A scene and a bare adapter take the same pair.\n */\nexport interface ViewPickGates {\n /** Painted alpha: the view's `alphaFor` times any per-node override alpha.\n * A node painted at alpha 0 cannot be hit. */\n alphaOf?: (id: string) => number;\n /** Whether a node's `layer` reaches the screen in the asking view. */\n layerIsPainted?: (layer: string) => boolean;\n}\n\n/** The gates a bare adapter takes from its view, plus how that view's camera\n * maps into each parallax layer — see `scenePlaneOf`. */\nexport interface AdapterPickGates extends ViewPickGates {\n planeOf?: (layer: string) => PlaneMap | null;\n}\n\nexport interface ScenePickSourceOptions<TPose> extends ViewPickGates {\n /** Pose lookup, when the caller holds an adapter that already resolves\n * overrides. Defaults to `effectivePose` against the scene's own. */\n getPose?: (id: string) => TPose;\n /** The asking view's composed alpha — `alphaFor(id)` times override alpha.\n * Defaults to the override alpha alone, which is all a bare scene knows. */\n alphaOf?: (id: string) => number;\n /** The asking view's answer to \"does this scene layer reach the screen\",\n * which is `layerVisibility` and `layerOrder` on top of the scene's own\n * `visible` flag. Consulted after the scene's flag, never instead of it. */\n layerIsPainted?: (layer: string) => boolean;\n /** The asking view's camera. With it, a layer carrying `parallax` is picked\n * through its plane; without it, every layer is taken to move with the\n * camera. */\n camera?: View;\n}\n\nexport function scenePickSource<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n opts: ScenePickSourceOptions<TPose> = {},\n): PickSource<TPose> {\n const hidden = hiddenLayerIds(scene.layers);\n const locked = lockedNodeTest(scene as never);\n const { getPose, alphaOf, layerIsPainted } = opts;\n\n // Resolved once per walk rather than once per candidate. Needs enumeration — a\n // partial scene stand-in carrying only `read` falls back to reading per node.\n let faded: Set<string> | null = null;\n const enumerable = typeof scene.overrides?.ids === 'function';\n if (!alphaOf && enumerable) {\n for (const id of scene.overrides.ids()) {\n const a = scene.overrides.read(id)?.alpha;\n if (a !== undefined && a <= 0) (faded ??= new Set()).add(id);\n }\n }\n const readAlpha = alphaOf\n ?? (enumerable\n ? (faded ? (id: string) => (faded.has(id) ? 0 : 1) : undefined)\n : (id: string) => scene.overrides.read(asNodeId(id))?.alpha ?? 1);\n\n // A composing strategy makes a node's own pose local, so picking folds the\n // parent chain the same way the render walk does: one definition of both.\n const paintedPoseOf = scenePaintedPoseOf(scene);\n const poseOf = getPose\n ? (node: PickCandidate<TPose>) => getPose(node.id)\n : (node: PickCandidate<TPose>) => paintedPoseOf(node as never);\n\n // Through `poseOf`, not the document pose: a derived node has to be tested\n // where the renderer draws its dependencies, which is what an override says.\n const childrenOf = (id: NodeId): readonly NodeId[] => scene.childrenOf(id);\n const depOf = (id: NodeId): DerivedDep<TPose> | undefined => {\n const dep = scene.get(id);\n if (dep === undefined) return undefined;\n return {\n node: dep as Node<unknown, string, TPose>,\n pose: poseOf(dep as never),\n get path(): Path | null {\n return resolveDerivedPath(dep as never, depOf, childrenOf);\n },\n };\n };\n\n const sceneDerivedPath = getPose ? null : sceneDerivedPathOf(scene);\n const derivedPathOf = (node: PickCandidate<TPose>): Path | null => {\n const n = node as unknown as Node<TData, TLayer, TPose>;\n if (!sceneDerivedPath) return n.dependsOn === undefined ? null : resolveDerivedPath(n, depOf, childrenOf);\n return showsComputedPath(scene, n) ? sceneDerivedPath(n) : null;\n };\n\n const planeOf = opts.camera ? scenePlaneOf(scene.layers, opts.camera) : null;\n\n return {\n ...(planeOf ? { planeOf } : {}),\n order: () => scene.renderOrderNodes() as unknown as readonly PickCandidate<TPose>[],\n derivedPathOf,\n poseOf,\n parentsOf(node) {\n let parentId = (node as { parent?: string | null }).parent ?? null;\n if (parentId === null) return EMPTY_PARENTS;\n const chain: PickCandidate<TPose>[] = [];\n const seen = new Set<string>();\n while (parentId !== null) {\n if (seen.has(parentId)) break;\n seen.add(parentId);\n const parent = scene.get(asNodeId(parentId));\n if (!parent) break;\n chain.push(parent as unknown as PickCandidate<TPose>);\n parentId = parent.parent ?? null;\n }\n return chain;\n },\n // Absent entirely when nothing is faded, so the walk skips the gate.\n ...(readAlpha ? { alphaOf: readAlpha } : {}),\n ...(locked ? { isLocked: (node: PickCandidate<TPose>) => locked(node.id) } : {}),\n ...(hidden.size > 0 || layerIsPainted\n ? {\n layerIsPainted: (layer: string) =>\n !hidden.has(layer) && (layerIsPainted === undefined || layerIsPainted(layer)),\n }\n : {}),\n };\n}\n\n/** Each parallax layer's plane map under `camera`, or null when no layer is a\n * plane — which keeps the per-layer lookup off the walk entirely. */\nexport function scenePlaneOf(\n layers: readonly { id: string; parallax?: ParallaxOpts }[] | undefined,\n camera: View,\n): ((layer: string) => PlaneMap | null) | null {\n let maps: Map<string, PlaneMap> | null = null;\n for (const l of layers ?? []) {\n if (l.parallax) (maps ??= new Map()).set(l.id, planeMap(camera, l.parallax));\n }\n if (maps === null) return null;\n const found = maps;\n return (layer) => found.get(layer) ?? null;\n}\n\nexport { adapterPickSource } from './adapterPickSource';\n"],"mappings":"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"}
@@ -3,22 +3,21 @@ import { definesFrame as r, effectivePose as i } from "../core/scene/effectivePo
3
3
  import { poseDescriptorForNode as a, translatePoseViaDescriptor as o, visualBoundsViaDescriptor as s } from "../core/geometry/poseDescriptor.js";
4
4
  import { AUTO_POSE_DESCRIPTOR as c } from "../core/geometry/autoPoseDescriptor.js";
5
5
  import { asNodeId as l } from "../core/scene/types.js";
6
- import { scenePoseTarget as u } from "../animation/poseTarget.js";
7
- import { sceneMutators as d } from "../core/scene/sceneMutators.js";
8
- import { applyOpsTo as f } from "../core/applyOps.js";
9
- import { hitTestArea as p, hitTestLassoPolygon as m, regionPickOptions as h } from "./deps/hitTestArea.js";
6
+ import { sceneMutators as u } from "../core/scene/sceneMutators.js";
7
+ import { applyOpsTo as d } from "../core/applyOps.js";
8
+ import { hitTestArea as f, hitTestLassoPolygon as p, regionPickOptions as m } from "./deps/hitTestArea.js";
9
+ import { scenePoseTarget as h } from "../animation/poseTarget.js";
10
10
  import { cascadingSetPose as g, containerCascade as _ } from "./poseCascade.js";
11
11
  import { pasteSceneSnapshot as v, snapshotSceneSelection as y } from "./sceneClipboard.js";
12
- import { useMemo as b } from "react";
13
12
  //#region src/canvas/sceneAdapter.ts
14
- function x(b, x = {}) {
13
+ function b(b, x = {}) {
15
14
  let S = () => {
16
15
  let e = /* @__PURE__ */ new Set();
17
16
  for (let t of b.layers) t.visible && e.add(t.id);
18
17
  return e;
19
18
  }, C = x.selection, w = C?.getSelection ?? C?.get ?? (() => []), T = C?.setSelection ?? C?.set ?? (() => {}), E = x.poseDescriptor ?? c, D = (e, t) => s(e, a(E, t)), O = (e, t, n, r) => o(e, t, n, r === void 0 ? E : a(E, r)), k = b.composition, A = t(k), j = {}, M = (e) => e ? {
20
19
  ...j,
21
- ...h(e, void 0)
20
+ ...m(e, void 0)
22
21
  } : j, N = A ? null : { setPose: g(b, E) }, P = {
23
22
  scene: b,
24
23
  composes: A,
@@ -27,7 +26,7 @@ function x(b, x = {}) {
27
26
  poseBounds: D,
28
27
  translate: O
29
28
  }, F = {
30
- ...d(b),
29
+ ...u(b),
31
30
  getNodes() {
32
31
  let e = S(), t = [];
33
32
  for (let n of b.renderOrderNodes()) e.has(n.layer) && t.push(n);
@@ -48,9 +47,9 @@ function x(b, x = {}) {
48
47
  ...A ? { composePose: k.compose } : {},
49
48
  ...N ? { setPose: (e, t) => N.setPose(l(e), t) } : {},
50
49
  poseTarget(e, t) {
51
- if (N === null || b.get(l(e))?.kind !== "container") return u(b, e, t ?? E);
50
+ if (N === null || b.get(l(e))?.kind !== "container") return h(b, e, t ?? E);
52
51
  let n = _(b, l(e), E, (t) => F.setPose(e, t));
53
- return u(b, e, t ?? E, n);
52
+ return h(b, e, t ?? E, n);
54
53
  },
55
54
  getLayers: () => b.layers.map((e) => ({
56
55
  id: e.id,
@@ -58,20 +57,17 @@ function x(b, x = {}) {
58
57
  parallax: e.parallax
59
58
  })),
60
59
  subscribeLayers: (e) => b.subscribe(e),
61
- getLayout(e) {
62
- let t = b.layoutOf(l(e));
63
- return t !== null || !x.layouts ? t : typeof x.layouts == "function" ? x.layouts(e) : x.layouts[e] ?? null;
64
- },
60
+ getLayout: (e) => b.layoutOf(l(e)),
65
61
  applyOps(e, t) {
66
- t === void 0 ? f(this, e) : b.applyBatch(e, t, this);
62
+ t === void 0 ? d(this, e) : b.applyBatch(e, t, this);
67
63
  },
68
64
  getSelection: w,
69
65
  setSelection: T,
70
66
  hitTestArea(e, t) {
71
- return p(b, e, M(t), E, { includeContainers: !0 });
67
+ return f(b, e, M(t), E, { includeContainers: !0 });
72
68
  },
73
69
  hitTestLasso(e, t, n) {
74
- return m(b, e, t, M(n), E, { includeContainers: !0 });
70
+ return p(b, e, t, M(n), E, { includeContainers: !0 });
75
71
  },
76
72
  ...x.commitInsert ? { commitInsert: (e) => {
77
73
  let t = x.commitInsert(e);
@@ -101,24 +97,7 @@ function x(b, x = {}) {
101
97
  };
102
98
  return F;
103
99
  }
104
- function S(e, t = {}) {
105
- let { selection: n, commitInsert: r, insertLayer: i, layouts: a, poseDescriptor: o } = t;
106
- return b(() => x(e, {
107
- selection: n,
108
- commitInsert: r,
109
- insertLayer: i,
110
- layouts: a,
111
- poseDescriptor: o
112
- }), [
113
- e,
114
- n,
115
- r,
116
- i,
117
- a,
118
- o
119
- ]);
120
- }
121
100
  //#endregion
122
- export { x as sceneToAdapter, S as useSceneAdapter };
101
+ export { b as sceneToAdapter };
123
102
 
124
103
  //# sourceMappingURL=sceneAdapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sceneAdapter.js","names":["sceneToAdapter","visibleLayers","out","layer","scene","sel","options","getSelection","setSelection","d","AUTO_POSE_DESCRIPTOR","poseBounds","visualBoundsViaDescriptor","p","poseDescriptorForNode","node","translate","translatePoseViaDescriptor","dx","dy","composition","composes","composesFrames","pickOpts","pickOptsFor","view","regionPickOptions","cascade","cascadingSetPose","clipboardEnv","adapter","id","frameAtOrAbove","sceneMutators","visible","nid","asNodeId","effectivePose","n","definesFrame","composeWorldPose","pose","scenePoseTarget","descriptor","carried","containerCascade","l","listener","declared","label","applyOpsTo","ops","hitTestArea","rect","hitTestLassoPolygon","polygon","mode","created","bounds","snapshotSceneSelection","ids","pasteSceneSnapshot","clipboard","offset","ctx","useSceneAdapter","useMemo","selection","commitInsert","insertLayer","layouts","poseDescriptor"],"sources":["../../src/canvas/sceneAdapter.ts"],"sourcesContent":["/**\n * Synthesize a `<Canvas>`-compatible adapter from a `Scene` primitive.\n * `getPose` / `setPose` return / write **local** coordinates (relative to\n * parent); world composition is the renderer's job via `composeWorldPose`.\n */\nimport { useMemo } from 'react';\nimport type {\n AreaSelectAdapter,\n ClipboardSnapshot,\n InsertAdapter,\n PasteCtx,\n LassoHitMode,\n LassoSelectAdapter,\n RegionPickView,\n LayerEnumerableAdapter,\n MoveAdapter,\n ResizeAdapter,\n RotateAdapter,\n} from 'core/adapters/types';\nimport type { LayoutStrategy } from '../layout/types';\nimport type { Op } from 'core/ops/types';\nimport type { Node, Scene } from 'core/scene/types';\nimport { definesFrame, effectivePose } from 'core/scene/effectivePose';\nimport { sceneMutators } from 'core/scene/sceneMutators';\nimport { asNodeId } from 'core/scene/types';\nimport { applyOpsTo } from 'core/applyOps';\nimport { hitTestArea, hitTestLassoPolygon, regionPickOptions } from 'canvas/deps/hitTestArea';\nimport type { ScenePickSourceOptions } from 'canvas/pickWalk';\nimport {\n poseDescriptorForNode,\n translatePoseViaDescriptor,\n visualBoundsViaDescriptor,\n type PoseDescriptor,\n} from 'interactions/actions/resize/geometry';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport { composesFrames, composeWorldPose, frameAtOrAbove } from 'core/scene/composePose';\nimport type { Bounds } from '../core/viewport/fitViewToBounds';\nimport { scenePoseTarget } from '../animation/poseTarget';\nimport { cascadingSetPose, containerCascade } from './poseCascade';\nimport { pasteSceneSnapshot, snapshotSceneSelection, type SceneClipboardEnv } from './sceneClipboard';\n\n/** Minimal selection contract `sceneToAdapter` needs to wire `getSelection` /\n * `setSelection`. Matches `useSelection().adapterMethods` plus an imperative\n * read; pass `useSelection()` itself or `selection.adapterMethods`. */\nexport interface SceneAdapterSelection {\n get?(): string[];\n set?(ids: string[]): void;\n getSelection?(): string[];\n setSelection?(ids: string[]): void;\n}\n\n/** Sibling z-order surface used by reorder ops. Inlined here (rather than\n * pulled from `core/ops/reorder` to avoid import cycles); the `null` parent\n * channel addresses the root sibling list. */\n/** @internal */\ninterface ReorderAdapter {\n getChildren(parentId: string | null): string[];\n setChildOrder(parentId: string | null, ids: string[]): void;\n}\n\n/** Everything the interaction layer can ask of a scene, as one type: the\n * move, resize, rotate, selection, layer and reorder contracts combined.\n * `<SceneCanvas>` synthesizes one of these, which is why most consumers never\n * touch an adapter directly. */\nexport type SceneCanvasAdapter<TData, TLayer extends string, TPose> =\n & MoveAdapter<Node<TData, TLayer, TPose>, TPose>\n & ResizeAdapter<Node<TData, TLayer, TPose>, TPose>\n & RotateAdapter<Node<TData, TLayer, TPose>, TPose>\n & AreaSelectAdapter\n & LassoSelectAdapter\n & LayerEnumerableAdapter<TLayer>\n & ReorderAdapter\n & Partial<InsertAdapter<Node<TData, TLayer, TPose>>>\n // Optional on the underlying adapter contracts, but unconditionally\n // provided by a scene-backed adapter.\n & {\n getParent(id: string): string | null;\n getLayers: NonNullable<LayerEnumerableAdapter<TLayer>['getLayers']>;\n /** The node's pose with every ancestor's frame folded in. Equal to\n * `getPose` unless the scene composes poses. */\n getWorldPose(id: string): TPose;\n /** Whether `id`'s pose is a frame its children are expressed in — see\n * `definesFrame`. */\n definesFrame(id: string): boolean;\n /** Present only when a composing strategy is configured; the render\n * walk feature-detects it. */\n composePose?(parent: TPose, child: TPose): TPose;\n getSelection(): string[];\n setSelection(ids: string[]): void;\n insertNode(node: Node<TData, TLayer, TPose>, index?: number): void;\n removeNode(id: string): void;\n /** Replace a node's `data` — what a `setData` op writes through. */\n setData(id: string, data: TData): void;\n /** Swap a container's layout — what a `setLayout` op writes through. */\n setLayout(id: string, layout: LayoutStrategy<TPose> | string | null): void;\n /** Move a node to another layer — what a `setLayer` op writes through. */\n setLayer(id: string, layer: TLayer): void;\n getRemovalClosure(ids: readonly string[]): string[];\n applyOps(ops: Op[], label?: string): void;\n snapshotSelection(ids: string[]): ClipboardSnapshot;\n commitPaste(\n clipboard: ClipboardSnapshot,\n offset: { dx: number; dy: number },\n ctx?: PasteCtx,\n ): Node<TData, TLayer, TPose>[];\n getPasteOffset(clipboard: ClipboardSnapshot): { dx: number; dy: number };\n };\n\n/** Optional extras for the synthesized adapter. Pass `commitInsert` to wire\n * the insert gesture into a Scene-owned canvas; the returned object becomes\n * a leaf on the layer named by `layer` (default `'default'`). */\nexport interface SceneToAdapterOptions<TData, TLayer extends string, TPose> {\n /** Factory for new objects. Returning `null` aborts the insert. */\n commitInsert?: (bounds: Bounds) => {\n pose: TPose;\n data: TData;\n id?: string;\n } | null;\n /** Layer to place inserted nodes on. Defaults to the trivial-form layer. */\n insertLayer?: TLayer;\n /** Selection source: the result of `useSelection()` (or its\n * `adapterMethods`). When omitted, `getSelection` returns `[]` and\n * `setSelection` is a noop, so the marquee gesture updates nothing. */\n selection?: SceneAdapterSelection;\n /** How to read and rewrite this scene's poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Layout strategies keyed by container node id, for containers whose\n * scene node declares none (`ContainerNode.layout` wins). `move` runs its\n * layout-aware pass on them; for inserts, deletes and resizes to reach\n * them too, install them with `useLayoutArrivals`. Pass either a static\n * map, or a `getLayout(id)` function for dynamic resolution. */\n layouts?:\n | Record<string, LayoutStrategy<TPose>>\n | ((containerId: string) => LayoutStrategy<TPose> | null);\n}\n\n/** Derive the adapter for a scene. Reads go straight to the scene; writes are\n * ops applied through its history, so anything done through the adapter is\n * undoable.\n *\n * Moving a container carries its contents either way the scene composes\n * poses. Under a frame (`scene.composition`) the one pose written moves them.\n * Under the absolute-pose model `setPose` on a container translates every\n * descendant by the same delta, and a batch that poses descendants too undoes\n * exactly only when it goes through this adapter's `applyOps`. */\nexport function sceneToAdapter<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n options: SceneToAdapterOptions<TData, TLayer, TPose> = {},\n): SceneCanvasAdapter<TData, TLayer, TPose> {\n const visibleLayers = (): Set<TLayer> => {\n const out = new Set<TLayer>();\n for (const layer of scene.layers) {\n if (layer.visible) out.add(layer.id);\n }\n return out;\n };\n\n const sel = options.selection;\n const getSelection = sel?.getSelection ?? sel?.get ?? (() => [] as string[]);\n const setSelection = sel?.setSelection ?? sel?.set ?? (() => {});\n const d = (options.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n const poseBounds = (p: TPose, node: unknown): Bounds =>\n visualBoundsViaDescriptor(p, poseDescriptorForNode(d, node));\n const translate = (p: TPose, dx: number, dy: number, node?: unknown): TPose =>\n translatePoseViaDescriptor(\n p, dx, dy, node === undefined ? d : poseDescriptorForNode(d, node),\n );\n\n const composition = scene.composition;\n const composes = composesFrames(composition);\n const pickOpts: ScenePickSourceOptions<unknown> = {};\n // The asking view's layer gate and camera, over the adapter's own options.\n const pickOptsFor = (view: RegionPickView | undefined): ScenePickSourceOptions<unknown> =>\n (view ? { ...pickOpts, ...regionPickOptions(view, undefined) } : pickOpts);\n\n const cascade = composes ? null : { setPose: cascadingSetPose(scene, d) };\n\n const clipboardEnv: SceneClipboardEnv<TData, TLayer, TPose> = {\n scene,\n composes,\n worldPoseOf: (id) => adapter.getWorldPose(id),\n frameAtOrAbove: (id) => frameAtOrAbove(adapter, id),\n poseBounds,\n translate,\n };\n\n const adapter: SceneCanvasAdapter<TData, TLayer, TPose> = {\n ...sceneMutators(scene),\n // What is shown, where the mutators' other users read the document:\n // visible layers only, and the effective pose.\n getNodes() {\n const visible = visibleLayers();\n const out: Node<TData, TLayer, TPose>[] = [];\n for (const n of scene.renderOrderNodes()) {\n if (visible.has(n.layer)) out.push(n);\n }\n return out;\n },\n getPose(id) {\n const nid = asNodeId(id);\n const n = scene.get(nid);\n if (!n) throw new Error(`sceneToAdapter: unknown node \"${id}\"`);\n return effectivePose(scene, n);\n },\n definesFrame(id) {\n const n = scene.get(asNodeId(id));\n return n === undefined || definesFrame(n);\n },\n getWorldPose(id) {\n if (!composes) return adapter.getPose(id);\n return composeWorldPose(adapter, id, composition.compose);\n },\n // Only present when it would do something: the render walk skips the fold\n // entirely when this is absent, which is the absolute-pose path.\n ...(composes ? { composePose: composition.compose } : {}),\n ...(cascade ? { setPose: (id: string, pose: TPose) => cascade.setPose(asNodeId(id), pose) } : {}),\n poseTarget(id, descriptor) {\n if (cascade === null || scene.get(asNodeId(id))?.kind !== 'container') {\n return scenePoseTarget(scene, id, descriptor ?? d);\n }\n // Its descendants hold poses of their own: a commit moves them, and they are shown beside it.\n const carried = containerCascade(scene, asNodeId(id), d, (pose) => adapter.setPose(id, pose));\n return scenePoseTarget(scene, id, descriptor ?? d, carried);\n },\n getLayers: () => scene.layers.map((l) => ({ id: l.id, visible: l.visible, parallax: l.parallax })),\n subscribeLayers: (listener) => scene.subscribe(listener),\n getLayout(id) {\n const declared = scene.layoutOf(asNodeId(id));\n if (declared !== null || !options.layouts) return declared;\n return typeof options.layouts === 'function'\n ? options.layouts(id)\n : options.layouts[id] ?? null;\n },\n // With a label the ops are one batch checkpoint; without one they are\n // applied transiently, with no checkpoint (the AreaSelectAdapter contract).\n applyOps(ops: Op[], label?: string) {\n if (label !== undefined) {\n scene.applyBatch(ops, label, this);\n } else {\n applyOpsTo(this, ops);\n }\n },\n getSelection,\n setSelection,\n // The live marquee's and lasso's own hit-tests. Containers come back:\n // this adapter's consumer has nothing to fold children into them.\n hitTestArea(rect: Bounds, view?: RegionPickView) {\n return hitTestArea(\n scene,\n rect,\n pickOptsFor(view),\n d as PoseDescriptor<unknown>,\n { includeContainers: true },\n );\n },\n hitTestLasso(polygon, mode: LassoHitMode, view?: RegionPickView) {\n return hitTestLassoPolygon(\n scene,\n polygon,\n mode,\n pickOptsFor(view),\n d as PoseDescriptor<unknown>,\n { includeContainers: true },\n );\n },\n // A pure factory: it constructs a Node spec but does NOT touch the scene.\n // The `InsertOp` → `adapter.insertNode` → `scene.add` path is the sole\n // insertion path. Calling `scene.add` here too would double-insert, and\n // the second add throws on id collision.\n ...(options.commitInsert\n ? {\n commitInsert: (bounds: { x: number; y: number; width: number; height: number }) => {\n const created = options.commitInsert!(bounds);\n if (!created) return null;\n const layer = (options.insertLayer ?? ('default' as TLayer));\n const id = created.id === undefined ? scene.mintId() : asNodeId(created.id);\n return {\n kind: 'leaf',\n id,\n layer,\n pose: created.pose,\n data: created.data,\n parent: null,\n } as Node<TData, TLayer, TPose>;\n },\n }\n : {}),\n // Clipboard seam (`useClipboardOps` / the paste ingestion path).\n snapshotSelection(ids: string[]): ClipboardSnapshot {\n return snapshotSceneSelection(clipboardEnv, ids);\n },\n commitPaste(\n clipboard: ClipboardSnapshot,\n offset: { dx: number; dy: number },\n ctx?: PasteCtx,\n ): Node<TData, TLayer, TPose>[] {\n return pasteSceneSnapshot(clipboardEnv, clipboard, offset, ctx);\n },\n // Constant cascade: the hook re-snapshots the just-created items, so\n // repeated pastes stack +12/+12 each time.\n getPasteOffset(): { dx: number; dy: number } {\n return { dx: 12, dy: 12 };\n },\n };\n\n return adapter;\n}\n\n/**\n * React-hook wrapper around `sceneToAdapter`. Memoizes on every option, so\n * the adapter keeps its identity across renders unless one of them changes.\n */\nexport function useSceneAdapter<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n options: SceneToAdapterOptions<TData, TLayer, TPose> = {},\n): SceneCanvasAdapter<TData, TLayer, TPose> {\n const {\n selection, commitInsert, insertLayer, layouts, poseDescriptor,\n } = options;\n return useMemo(\n () => sceneToAdapter(scene, {\n selection, commitInsert, insertLayer, layouts, poseDescriptor,\n }),\n [scene, selection, commitInsert, insertLayer, layouts, poseDescriptor],\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sceneAdapter.js","names":["sceneToAdapter","visibleLayers","out","layer","scene","sel","options","getSelection","setSelection","d","AUTO_POSE_DESCRIPTOR","poseBounds","visualBoundsViaDescriptor","p","poseDescriptorForNode","node","translate","translatePoseViaDescriptor","dx","dy","composition","composes","composesFrames","pickOpts","pickOptsFor","view","regionPickOptions","cascade","cascadingSetPose","clipboardEnv","adapter","id","frameAtOrAbove","sceneMutators","visible","nid","asNodeId","effectivePose","n","definesFrame","composeWorldPose","pose","scenePoseTarget","descriptor","carried","containerCascade","l","listener","label","applyOpsTo","ops","hitTestArea","rect","hitTestLassoPolygon","polygon","mode","created","bounds","snapshotSceneSelection","ids","pasteSceneSnapshot","clipboard","offset","ctx"],"sources":["../../src/canvas/sceneAdapter.ts"],"sourcesContent":["/**\n * Synthesize a `<Canvas>`-compatible adapter from a `Scene` primitive.\n * `getPose` / `setPose` return / write **local** coordinates (relative to\n * parent); world composition is the renderer's job via `composeWorldPose`.\n */\nimport type {\n AreaSelectAdapter,\n ClipboardSnapshot,\n InsertAdapter,\n PasteCtx,\n LassoHitMode,\n LassoSelectAdapter,\n RegionPickView,\n LayerEnumerableAdapter,\n MoveAdapter,\n ResizeAdapter,\n RotateAdapter,\n} from 'core/adapters/types';\nimport type { LayoutStrategy } from '../layout/types';\nimport type { Op } from 'core/ops/types';\nimport type { Node, Scene } from 'core/scene/types';\nimport { definesFrame, effectivePose } from 'core/scene/effectivePose';\nimport { sceneMutators } from 'core/scene/sceneMutators';\nimport { asNodeId } from 'core/scene/types';\nimport { applyOpsTo } from 'core/applyOps';\nimport { hitTestArea, hitTestLassoPolygon, regionPickOptions } from 'canvas/deps/hitTestArea';\nimport type { ScenePickSourceOptions } from 'canvas/pickWalk';\nimport {\n poseDescriptorForNode,\n translatePoseViaDescriptor,\n visualBoundsViaDescriptor,\n type PoseDescriptor,\n} from 'interactions/actions/resize/geometry';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport { composesFrames, composeWorldPose, frameAtOrAbove } from 'core/scene/composePose';\nimport type { Bounds } from '../core/viewport/fitViewToBounds';\nimport { scenePoseTarget } from '../animation/poseTarget';\nimport { cascadingSetPose, containerCascade } from './poseCascade';\nimport { pasteSceneSnapshot, snapshotSceneSelection, type SceneClipboardEnv } from './sceneClipboard';\n\n/** Minimal selection contract `sceneToAdapter` needs to wire `getSelection` /\n * `setSelection`. Matches `useSelection().adapterMethods` plus an imperative\n * read; pass `useSelection()` itself or `selection.adapterMethods`. */\nexport interface SceneAdapterSelection {\n get?(): string[];\n set?(ids: string[]): void;\n getSelection?(): string[];\n setSelection?(ids: string[]): void;\n}\n\n/** Sibling z-order surface used by reorder ops. Inlined here (rather than\n * pulled from `core/ops/reorder` to avoid import cycles); the `null` parent\n * channel addresses the root sibling list. */\n/** @internal */\ninterface ReorderAdapter {\n getChildren(parentId: string | null): string[];\n setChildOrder(parentId: string | null, ids: string[]): void;\n}\n\n/** Everything the interaction layer can ask of a scene, as one type: the\n * move, resize, rotate, selection, layer and reorder contracts combined.\n * `<SceneCanvas>` synthesizes one of these, which is why most consumers never\n * touch an adapter directly. */\nexport type SceneCanvasAdapter<TData, TLayer extends string, TPose> =\n & MoveAdapter<Node<TData, TLayer, TPose>, TPose>\n & ResizeAdapter<Node<TData, TLayer, TPose>, TPose>\n & RotateAdapter<Node<TData, TLayer, TPose>, TPose>\n & AreaSelectAdapter\n & LassoSelectAdapter\n & LayerEnumerableAdapter<TLayer>\n & ReorderAdapter\n & Partial<InsertAdapter<Node<TData, TLayer, TPose>>>\n // Optional on the underlying adapter contracts, but unconditionally\n // provided by a scene-backed adapter.\n & {\n getParent(id: string): string | null;\n getLayers: NonNullable<LayerEnumerableAdapter<TLayer>['getLayers']>;\n /** The node's pose with every ancestor's frame folded in. Equal to\n * `getPose` unless the scene composes poses. */\n getWorldPose(id: string): TPose;\n /** Whether `id`'s pose is a frame its children are expressed in — see\n * `definesFrame`. */\n definesFrame(id: string): boolean;\n /** Present only when a composing strategy is configured; the render\n * walk feature-detects it. */\n composePose?(parent: TPose, child: TPose): TPose;\n getSelection(): string[];\n setSelection(ids: string[]): void;\n insertNode(node: Node<TData, TLayer, TPose>, index?: number): void;\n removeNode(id: string): void;\n /** Replace a node's `data` — what a `setData` op writes through. */\n setData(id: string, data: TData): void;\n /** Swap a container's layout — what a `setLayout` op writes through. */\n setLayout(id: string, layout: LayoutStrategy<TPose> | string | null): void;\n /** Move a node to another layer — what a `setLayer` op writes through. */\n setLayer(id: string, layer: TLayer): void;\n getRemovalClosure(ids: readonly string[]): string[];\n applyOps(ops: Op[], label?: string): void;\n snapshotSelection(ids: string[]): ClipboardSnapshot;\n commitPaste(\n clipboard: ClipboardSnapshot,\n offset: { dx: number; dy: number },\n ctx?: PasteCtx,\n ): Node<TData, TLayer, TPose>[];\n getPasteOffset(clipboard: ClipboardSnapshot): { dx: number; dy: number };\n };\n\n/** Optional extras for the synthesized adapter. Pass `commitInsert` to wire\n * the insert gesture into a Scene-owned canvas; the returned object becomes\n * a leaf on the layer named by `layer` (default `'default'`). */\nexport interface SceneToAdapterOptions<TData, TLayer extends string, TPose> {\n /** Factory for new objects. Returning `null` aborts the insert. */\n commitInsert?: (bounds: Bounds) => {\n pose: TPose;\n data: TData;\n id?: string;\n } | null;\n /** Layer to place inserted nodes on. Defaults to the trivial-form layer. */\n insertLayer?: TLayer;\n /** Selection source: the result of `useSelection()` (or its\n * `adapterMethods`). When omitted, `getSelection` returns `[]` and\n * `setSelection` is a noop, so the marquee gesture updates nothing. */\n selection?: SceneAdapterSelection;\n /** How to read and rewrite this scene's poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n}\n\n/** Derive the adapter for a scene. Reads go straight to the scene; writes are\n * ops applied through its history, so anything done through the adapter is\n * undoable.\n *\n * Moving a container carries its contents either way the scene composes\n * poses. Under a frame (`scene.composition`) the one pose written moves them.\n * Under the absolute-pose model `setPose` on a container translates every\n * descendant by the same delta, and a batch that poses descendants too undoes\n * exactly only when it goes through this adapter's `applyOps`. */\nexport function sceneToAdapter<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n options: SceneToAdapterOptions<TData, TLayer, TPose> = {},\n): SceneCanvasAdapter<TData, TLayer, TPose> {\n const visibleLayers = (): Set<TLayer> => {\n const out = new Set<TLayer>();\n for (const layer of scene.layers) {\n if (layer.visible) out.add(layer.id);\n }\n return out;\n };\n\n const sel = options.selection;\n const getSelection = sel?.getSelection ?? sel?.get ?? (() => [] as string[]);\n const setSelection = sel?.setSelection ?? sel?.set ?? (() => {});\n const d = (options.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n const poseBounds = (p: TPose, node: unknown): Bounds =>\n visualBoundsViaDescriptor(p, poseDescriptorForNode(d, node));\n const translate = (p: TPose, dx: number, dy: number, node?: unknown): TPose =>\n translatePoseViaDescriptor(\n p, dx, dy, node === undefined ? d : poseDescriptorForNode(d, node),\n );\n\n const composition = scene.composition;\n const composes = composesFrames(composition);\n const pickOpts: ScenePickSourceOptions<unknown> = {};\n // The asking view's layer gate and camera, over the adapter's own options.\n const pickOptsFor = (view: RegionPickView | undefined): ScenePickSourceOptions<unknown> =>\n (view ? { ...pickOpts, ...regionPickOptions(view, undefined) } : pickOpts);\n\n const cascade = composes ? null : { setPose: cascadingSetPose(scene, d) };\n\n const clipboardEnv: SceneClipboardEnv<TData, TLayer, TPose> = {\n scene,\n composes,\n worldPoseOf: (id) => adapter.getWorldPose(id),\n frameAtOrAbove: (id) => frameAtOrAbove(adapter, id),\n poseBounds,\n translate,\n };\n\n const adapter: SceneCanvasAdapter<TData, TLayer, TPose> = {\n ...sceneMutators(scene),\n // What is shown, where the mutators' other users read the document:\n // visible layers only, and the effective pose.\n getNodes() {\n const visible = visibleLayers();\n const out: Node<TData, TLayer, TPose>[] = [];\n for (const n of scene.renderOrderNodes()) {\n if (visible.has(n.layer)) out.push(n);\n }\n return out;\n },\n getPose(id) {\n const nid = asNodeId(id);\n const n = scene.get(nid);\n if (!n) throw new Error(`sceneToAdapter: unknown node \"${id}\"`);\n return effectivePose(scene, n);\n },\n definesFrame(id) {\n const n = scene.get(asNodeId(id));\n return n === undefined || definesFrame(n);\n },\n getWorldPose(id) {\n if (!composes) return adapter.getPose(id);\n return composeWorldPose(adapter, id, composition.compose);\n },\n // Only present when it would do something: the render walk skips the fold\n // entirely when this is absent, which is the absolute-pose path.\n ...(composes ? { composePose: composition.compose } : {}),\n ...(cascade ? { setPose: (id: string, pose: TPose) => cascade.setPose(asNodeId(id), pose) } : {}),\n poseTarget(id, descriptor) {\n if (cascade === null || scene.get(asNodeId(id))?.kind !== 'container') {\n return scenePoseTarget(scene, id, descriptor ?? d);\n }\n // Its descendants hold poses of their own: a commit moves them, and they are shown beside it.\n const carried = containerCascade(scene, asNodeId(id), d, (pose) => adapter.setPose(id, pose));\n return scenePoseTarget(scene, id, descriptor ?? d, carried);\n },\n getLayers: () => scene.layers.map((l) => ({ id: l.id, visible: l.visible, parallax: l.parallax })),\n subscribeLayers: (listener) => scene.subscribe(listener),\n getLayout: (id) => scene.layoutOf(asNodeId(id)),\n // With a label the ops are one batch checkpoint; without one they are\n // applied transiently, with no checkpoint (the AreaSelectAdapter contract).\n applyOps(ops: Op[], label?: string) {\n if (label !== undefined) {\n scene.applyBatch(ops, label, this);\n } else {\n applyOpsTo(this, ops);\n }\n },\n getSelection,\n setSelection,\n // The live marquee's and lasso's own hit-tests. Containers come back:\n // this adapter's consumer has nothing to fold children into them.\n hitTestArea(rect: Bounds, view?: RegionPickView) {\n return hitTestArea(\n scene,\n rect,\n pickOptsFor(view),\n d as PoseDescriptor<unknown>,\n { includeContainers: true },\n );\n },\n hitTestLasso(polygon, mode: LassoHitMode, view?: RegionPickView) {\n return hitTestLassoPolygon(\n scene,\n polygon,\n mode,\n pickOptsFor(view),\n d as PoseDescriptor<unknown>,\n { includeContainers: true },\n );\n },\n // A pure factory: it constructs a Node spec but does NOT touch the scene.\n // The `InsertOp` → `adapter.insertNode` → `scene.add` path is the sole\n // insertion path. Calling `scene.add` here too would double-insert, and\n // the second add throws on id collision.\n ...(options.commitInsert\n ? {\n commitInsert: (bounds: { x: number; y: number; width: number; height: number }) => {\n const created = options.commitInsert!(bounds);\n if (!created) return null;\n const layer = (options.insertLayer ?? ('default' as TLayer));\n const id = created.id === undefined ? scene.mintId() : asNodeId(created.id);\n return {\n kind: 'leaf',\n id,\n layer,\n pose: created.pose,\n data: created.data,\n parent: null,\n } as Node<TData, TLayer, TPose>;\n },\n }\n : {}),\n // Clipboard seam (`useClipboardOps` / the paste ingestion path).\n snapshotSelection(ids: string[]): ClipboardSnapshot {\n return snapshotSceneSelection(clipboardEnv, ids);\n },\n commitPaste(\n clipboard: ClipboardSnapshot,\n offset: { dx: number; dy: number },\n ctx?: PasteCtx,\n ): Node<TData, TLayer, TPose>[] {\n return pasteSceneSnapshot(clipboardEnv, clipboard, offset, ctx);\n },\n // Constant cascade: the hook re-snapshots the just-created items, so\n // repeated pastes stack +12/+12 each time.\n getPasteOffset(): { dx: number; dy: number } {\n return { dx: 12, dy: 12 };\n },\n };\n\n return adapter;\n}\n"],"mappings":"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"}
@@ -1,20 +1,21 @@
1
- import { sceneDerivedPathOf as e, withDerivedPaths as t } from "./derivedPath.js";
2
- import { withColorOverrides as n } from "./colorOverrides.js";
1
+ import { sceneDerivedPathOf as e, sceneShownToPose as t, withDerivedPaths as n } from "./derivedPath.js";
2
+ import { withColorOverrides as r } from "./colorOverrides.js";
3
3
  //#region src/canvas/sceneSlotWiring.ts
4
- function r(e, t) {
4
+ function i(e, t) {
5
5
  let n = (t) => e.overrides.read(t)?.alpha ?? 1;
6
6
  return t ? (e) => t(e) * n(e) : n;
7
7
  }
8
- function i(i, a, o, s) {
9
- let c = t(a, i.drawOne, i.toPose), l = e(a, i.toPose);
8
+ function a(a, o, s, c) {
9
+ let l = n(o, a.drawOne, a.toPose), u = e(o, a.toPose);
10
10
  return {
11
- ...i,
12
- drawOne: s ? n(s, c) : c,
13
- derivedPathOf: l,
14
- alphaFor: r(a, o)
11
+ ...a,
12
+ ...a.toPose ? { toPose: t(o, a.toPose) } : {},
13
+ drawOne: c ? r(c, l) : l,
14
+ derivedPathOf: u,
15
+ alphaFor: i(o, s)
15
16
  };
16
17
  }
17
18
  //#endregion
18
- export { r as composeAlphaFor, i as wireSceneSlotToScene };
19
+ export { i as composeAlphaFor, a as wireSceneSlotToScene };
19
20
 
20
21
  //# sourceMappingURL=sceneSlotWiring.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sceneSlotWiring.js","names":["composeAlphaFor","overrideAlphaFor","scene","id","alphaFor","wireSceneSlotToScene","derived","withDerivedPaths","slot","derivedPathOf","sceneDerivedPathOf","colorOverrides","withColorOverrides"],"sources":["../../src/canvas/sceneSlotWiring.ts"],"sourcesContent":["/**\n * What the scene slot needs from the `Scene` that `<Canvas>` cannot see.\n *\n * `<Canvas>` is scene-agnostic: it walks an adapter. Three things a node is\n * painted with are therefore invisible to it — an ephemeral override's alpha, a\n * derived path, which needs other nodes' poses to resolve, and animated vertex\n * colors, which live in an animator. `<SceneCanvas>` folds them into the slot\n * here; `buildSceneViewCommands` does the same for the headless walk.\n */\nimport type { SceneSlotConfig } from './buildSceneLayer';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { withDerivedPaths, sceneDerivedPathOf } from './derivedPath';\nimport { withColorOverrides } from './colorOverrides';\nimport type { ColorOverrideRegistry } from '@weasel-js/animator';\n\n/**\n * The alpha a view paints a node at: the view's own `alphaFor` times any\n * ephemeral override alpha.\n *\n * The hit path asks this too — a node painted at alpha 0 is not on screen and\n * must not claim clicks — so it is one function rather than the painter's and\n * picking's separate readings of the same two inputs.\n */\nexport function composeAlphaFor<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n alphaFor?: (id: string) => number,\n): (id: string) => number {\n const overrideAlphaFor = (id: string) => scene.overrides.read(id as NodeId)?.alpha ?? 1;\n return alphaFor ? (id: string) => alphaFor(id) * overrideAlphaFor(id) : overrideAlphaFor;\n}\n\nexport function wireSceneSlotToScene<TData, TLayer extends string, TPose>(\n slot: SceneSlotConfig<Node<TData, TLayer, TPose>, TPose>,\n scene: Scene<TData, TLayer, TPose>,\n alphaFor?: (id: string) => number,\n colorOverrides?: ColorOverrideRegistry,\n): SceneSlotConfig<Node<TData, TLayer, TPose>, TPose> {\n const derived = withDerivedPaths(scene, slot.drawOne, slot.toPose);\n const derivedPathOf = sceneDerivedPathOf(scene, slot.toPose);\n return {\n ...slot,\n drawOne: colorOverrides ? withColorOverrides(colorOverrides, derived) : derived,\n derivedPathOf,\n alphaFor: composeAlphaFor(scene, alphaFor),\n };\n}\n"],"mappings":";;;AAuBA,SAAgBA,EACd,GACA,GACwB;CACxB,IAAMC,KAAoB,MAAeC,EAAM,UAAU,KAAKC,CAAY,CAAC,EAAE,SAAS;CACtF,OAAOC,KAAY,MAAeA,EAASD,CAAE,IAAIF,EAAiBE,CAAE,IAAIF;AAC1E;AAEA,SAAgBI,EACd,GACA,GACA,GACA,GACoD;CACpD,IAAMC,IAAUC,EAAiBL,GAAOM,EAAK,SAASA,EAAK,MAAM,GAC3DC,IAAgBC,EAAmBR,GAAOM,EAAK,MAAM;CAC3D,OAAO;EACL,GAAGA;EACH,SAASG,IAAiBC,EAAmBD,GAAgBL,CAAO,IAAIA;EACxE;EACA,UAAUN,EAAgBE,GAAOE,CAAQ;CAC3C;AACF"}
1
+ {"version":3,"file":"sceneSlotWiring.js","names":["composeAlphaFor","overrideAlphaFor","scene","id","alphaFor","wireSceneSlotToScene","derived","withDerivedPaths","slot","derivedPathOf","sceneDerivedPathOf","sceneShownToPose","colorOverrides","withColorOverrides"],"sources":["../../src/canvas/sceneSlotWiring.ts"],"sourcesContent":["/**\n * What the scene slot needs from the `Scene` that `<Canvas>` cannot see.\n *\n * `<Canvas>` is scene-agnostic: it walks an adapter. Three things a node is\n * painted with are therefore invisible to it — an ephemeral override's alpha, a\n * derived path, which needs other nodes' poses to resolve, and animated vertex\n * colors, which live in an animator. `<SceneCanvas>` folds them into the slot\n * here; `buildSceneViewCommands` does the same for the headless walk.\n */\nimport type { SceneSlotConfig } from './buildSceneLayer';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { withDerivedPaths, sceneDerivedPathOf, sceneShownToPose } from './derivedPath';\nimport { withColorOverrides } from './colorOverrides';\nimport type { ColorOverrideRegistry } from '@weasel-js/animator';\n\n/**\n * The alpha a view paints a node at: the view's own `alphaFor` times any\n * ephemeral override alpha.\n *\n * The hit path asks this too — a node painted at alpha 0 is not on screen and\n * must not claim clicks — so it is one function rather than the painter's and\n * picking's separate readings of the same two inputs.\n */\nexport function composeAlphaFor<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n alphaFor?: (id: string) => number,\n): (id: string) => number {\n const overrideAlphaFor = (id: string) => scene.overrides.read(id as NodeId)?.alpha ?? 1;\n return alphaFor ? (id: string) => alphaFor(id) * overrideAlphaFor(id) : overrideAlphaFor;\n}\n\nexport function wireSceneSlotToScene<TData, TLayer extends string, TPose>(\n slot: SceneSlotConfig<Node<TData, TLayer, TPose>, TPose>,\n scene: Scene<TData, TLayer, TPose>,\n alphaFor?: (id: string) => number,\n colorOverrides?: ColorOverrideRegistry,\n): SceneSlotConfig<Node<TData, TLayer, TPose>, TPose> {\n const derived = withDerivedPaths(scene, slot.drawOne, slot.toPose);\n const derivedPathOf = sceneDerivedPathOf(scene, slot.toPose);\n return {\n ...slot,\n ...(slot.toPose ? { toPose: sceneShownToPose(scene, slot.toPose) } : {}),\n drawOne: colorOverrides ? withColorOverrides(colorOverrides, derived) : derived,\n derivedPathOf,\n alphaFor: composeAlphaFor(scene, alphaFor),\n };\n}\n"],"mappings":";;;AAuBA,SAAgBA,EACd,GACA,GACwB;CACxB,IAAMC,KAAoB,MAAeC,EAAM,UAAU,KAAKC,CAAY,CAAC,EAAE,SAAS;CACtF,OAAOC,KAAY,MAAeA,EAASD,CAAE,IAAIF,EAAiBE,CAAE,IAAIF;AAC1E;AAEA,SAAgBI,EACd,GACA,GACA,GACA,GACoD;CACpD,IAAMC,IAAUC,EAAiBL,GAAOM,EAAK,SAASA,EAAK,MAAM,GAC3DC,IAAgBC,EAAmBR,GAAOM,EAAK,MAAM;CAC3D,OAAO;EACL,GAAGA;EACH,GAAIA,EAAK,SAAS,EAAE,QAAQG,EAAiBT,GAAOM,EAAK,MAAM,EAAE,IAAI,CAAC;EACtE,SAASI,IAAiBC,EAAmBD,GAAgBN,CAAO,IAAIA;EACxE;EACA,UAAUN,EAAgBE,GAAOE,CAAQ;CAC3C;AACF"}