@weasel-js/core 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (586) hide show
  1. package/CHANGELOG.md +611 -0
  2. package/README.md +1 -1
  3. package/dist/WeaselProvider.js +1 -1
  4. package/dist/affordances/pathAnchors.js +10 -6
  5. package/dist/affordances/pathAnchors.js.map +1 -1
  6. package/dist/animation/index.js +3 -3
  7. package/dist/animation/rig/bindRig.js +1 -1
  8. package/dist/animation/rig/rigNode.js.map +1 -1
  9. package/dist/barrel/canvas.js +9 -3
  10. package/dist/barrel/interactions.js +5 -4
  11. package/dist/barrel/paint.js +4 -4
  12. package/dist/barrel/paths.js +10 -6
  13. package/dist/barrel/renderer.js +5 -3
  14. package/dist/barrel/routing.js +7 -12
  15. package/dist/barrel/scene.js +9 -5
  16. package/dist/barrel/text.js +2 -2
  17. package/dist/barrel/viewport.js +9 -4
  18. package/dist/canvas/Canvas.js +5 -2
  19. package/dist/canvas/Canvas.js.map +1 -1
  20. package/dist/canvas/CanvasView.js +23 -34
  21. package/dist/canvas/CanvasView.js.map +1 -1
  22. package/dist/canvas/ModalityHud.js +1 -1
  23. package/dist/canvas/NodeShape.js +4 -1
  24. package/dist/canvas/NodeShape.js.map +1 -1
  25. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
  26. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
  27. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
  28. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
  29. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
  30. package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
  31. package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
  32. package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
  33. package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
  34. package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -0
  35. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
  36. package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
  37. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  38. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
  39. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  40. package/dist/canvas/SceneCanvas/features.js +45 -5
  41. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  42. package/dist/canvas/SceneCanvas/props.js +1 -11
  43. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  44. package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
  45. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  46. package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
  47. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  48. package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
  49. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
  50. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
  51. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  52. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  53. package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
  54. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
  55. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +94 -0
  56. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
  57. package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
  58. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/useCanvasTools.js +15 -10
  60. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  61. package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
  62. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
  63. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
  64. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
  65. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
  66. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  67. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -3
  68. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
  69. package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
  70. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  71. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +24 -7
  72. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
  73. package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
  74. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
  75. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
  76. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  77. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -5
  78. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
  79. package/dist/canvas/SceneCanvas.js +27 -24
  80. package/dist/canvas/SceneCanvas.js.map +1 -1
  81. package/dist/canvas/SurfaceCanvas.js +5 -22
  82. package/dist/canvas/SurfaceCanvas.js.map +1 -1
  83. package/dist/canvas/ViewMarker.js +35 -0
  84. package/dist/canvas/ViewMarker.js.map +1 -0
  85. package/dist/canvas/canvasRenderer.js +9 -5
  86. package/dist/canvas/canvasRenderer.js.map +1 -1
  87. package/dist/canvas/contextAttributes.js +14 -0
  88. package/dist/canvas/contextAttributes.js.map +1 -0
  89. package/dist/canvas/defaultDrawOne.js +2 -0
  90. package/dist/canvas/defaultDrawOne.js.map +1 -1
  91. package/dist/canvas/deps/booleans.js +2 -1
  92. package/dist/canvas/deps/booleans.js.map +1 -1
  93. package/dist/canvas/deps/editAnchors.js +9 -113
  94. package/dist/canvas/deps/editAnchors.js.map +1 -1
  95. package/dist/canvas/deps/hitTestArea.js +2 -2
  96. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  97. package/dist/canvas/deps/insert.js +10 -4
  98. package/dist/canvas/deps/insert.js.map +1 -1
  99. package/dist/canvas/deps/pathEditCommits.js +189 -0
  100. package/dist/canvas/deps/pathEditCommits.js.map +1 -0
  101. package/dist/canvas/deps/snap.js +12 -9
  102. package/dist/canvas/deps/snap.js.map +1 -1
  103. package/dist/canvas/deps/transformFollowers.js +20 -0
  104. package/dist/canvas/deps/transformFollowers.js.map +1 -0
  105. package/dist/canvas/derivedPath.js +20 -1
  106. package/dist/canvas/derivedPath.js.map +1 -1
  107. package/dist/canvas/drawnBounds.js +38 -4
  108. package/dist/canvas/drawnBounds.js.map +1 -1
  109. package/dist/canvas/inheritedPaints.js +44 -0
  110. package/dist/canvas/inheritedPaints.js.map +1 -0
  111. package/dist/canvas/nodeShapes/derivedPainter.js +23 -16
  112. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  113. package/dist/canvas/nodeShapes/nodePaint.js +13 -34
  114. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  115. package/dist/canvas/nodeShapes/pathPainter.js +12 -10
  116. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  117. package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
  118. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  119. package/dist/canvas/nodeShapes/shapePainter.js +12 -11
  120. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  121. package/dist/canvas/nodeShapes/textPainter.js +13 -12
  122. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  123. package/dist/canvas/overlayRoleStrokes.js +12 -0
  124. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  125. package/dist/canvas/pathOverlay.js +27 -7
  126. package/dist/canvas/pathOverlay.js.map +1 -1
  127. package/dist/canvas/pickReach.js +3 -3
  128. package/dist/canvas/pickReach.js.map +1 -1
  129. package/dist/canvas/pickWalk.js +3 -1
  130. package/dist/canvas/pickWalk.js.map +1 -1
  131. package/dist/canvas/renderDebugSnapshot.js +1 -0
  132. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  133. package/dist/canvas/renderSceneToPixels.js +7 -6
  134. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  135. package/dist/canvas/sceneAdapter.js.map +1 -1
  136. package/dist/canvas/sceneSlotWiring.js +2 -1
  137. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  138. package/dist/canvas/sceneViewRender.js +2 -1
  139. package/dist/canvas/sceneViewRender.js.map +1 -1
  140. package/dist/canvas/surfaceContribution.js +12 -8
  141. package/dist/canvas/surfaceContribution.js.map +1 -1
  142. package/dist/canvas/useCanvasPaint.js +2 -1
  143. package/dist/canvas/useCanvasPaint.js.map +1 -1
  144. package/dist/canvas/useCanvasView.js +4 -2
  145. package/dist/canvas/useCanvasView.js.map +1 -1
  146. package/dist/canvas/useInFlightBounds.js +52 -0
  147. package/dist/canvas/useInFlightBounds.js.map +1 -0
  148. package/dist/canvas/useLayerStack.js +6 -2
  149. package/dist/canvas/useLayerStack.js.map +1 -1
  150. package/dist/canvas/useViewAim.js +121 -0
  151. package/dist/canvas/useViewAim.js.map +1 -0
  152. package/dist/canvas/useViewHelpers.js +7 -9
  153. package/dist/canvas/useViewHelpers.js.map +1 -1
  154. package/dist/canvas/useViewNesting.js +3 -2
  155. package/dist/canvas/useViewNesting.js.map +1 -1
  156. package/dist/canvas/useViewRegistrySurface.js +4 -2
  157. package/dist/canvas/useViewRegistrySurface.js.map +1 -1
  158. package/dist/canvas/viewMarkers.js +63 -0
  159. package/dist/canvas/viewMarkers.js.map +1 -0
  160. package/dist/canvas/viewRegistry.js +27 -1
  161. package/dist/canvas/viewRegistry.js.map +1 -1
  162. package/dist/clipboard.d.ts +3 -2
  163. package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
  164. package/dist/clone.d.ts +4 -3
  165. package/dist/core/geometry/autoPoseDescriptor.js +1 -1
  166. package/dist/core/ops/setDependsOn.js +37 -0
  167. package/dist/core/ops/setDependsOn.js.map +1 -0
  168. package/dist/core/ops/writtenBy.js +53 -0
  169. package/dist/core/ops/writtenBy.js.map +1 -0
  170. package/dist/core/pages/fitViewToPage.js +12 -1
  171. package/dist/core/pages/fitViewToPage.js.map +1 -1
  172. package/dist/core/pages/pageEdits.js +163 -0
  173. package/dist/core/pages/pageEdits.js.map +1 -0
  174. package/dist/core/pages/pages.js +30 -1
  175. package/dist/core/pages/pages.js.map +1 -1
  176. package/dist/core/paint/meshKindLazy.js +59 -2
  177. package/dist/core/paint/meshKindLazy.js.map +1 -1
  178. package/dist/core/scene/NodeRouting.js +8 -3
  179. package/dist/core/scene/NodeRouting.js.map +1 -1
  180. package/dist/core/scene/arrivalWindow.js.map +1 -1
  181. package/dist/core/scene/carryDescendants.js +51 -0
  182. package/dist/core/scene/carryDescendants.js.map +1 -0
  183. package/dist/core/scene/clipNothing.js +13 -0
  184. package/dist/core/scene/clipNothing.js.map +1 -0
  185. package/dist/core/scene/depMemo.js +11 -3
  186. package/dist/core/scene/depMemo.js.map +1 -1
  187. package/dist/core/scene/dependents.js +7 -1
  188. package/dist/core/scene/dependents.js.map +1 -1
  189. package/dist/core/scene/derivedParts.js +10 -11
  190. package/dist/core/scene/derivedParts.js.map +1 -1
  191. package/dist/core/scene/docValues.js +57 -0
  192. package/dist/core/scene/docValues.js.map +1 -0
  193. package/dist/core/scene/editPass.js +111 -0
  194. package/dist/core/scene/editPass.js.map +1 -0
  195. package/dist/core/scene/effectivePose.js +13 -2
  196. package/dist/core/scene/effectivePose.js.map +1 -1
  197. package/dist/core/scene/fieldEdits.js +4 -1
  198. package/dist/core/scene/fieldEdits.js.map +1 -1
  199. package/dist/core/scene/fontReads.js +37 -0
  200. package/dist/core/scene/fontReads.js.map +1 -0
  201. package/dist/core/scene/historyFacade.js +1 -0
  202. package/dist/core/scene/historyFacade.js.map +1 -1
  203. package/dist/core/scene/inheritedPaint.js +75 -0
  204. package/dist/core/scene/inheritedPaint.js.map +1 -0
  205. package/dist/core/scene/kitRegistry.js +5 -0
  206. package/dist/core/scene/kitRegistry.js.map +1 -1
  207. package/dist/core/scene/layoutPass.js +28 -3
  208. package/dist/core/scene/layoutPass.js.map +1 -1
  209. package/dist/core/scene/nodeMemo.js +15 -7
  210. package/dist/core/scene/nodeMemo.js.map +1 -1
  211. package/dist/core/scene/pathEffects/blend.js.map +1 -1
  212. package/dist/core/scene/pathEffects/derive.js +7 -2
  213. package/dist/core/scene/pathEffects/derive.js.map +1 -1
  214. package/dist/core/scene/pathEffects/effects.js +3 -1
  215. package/dist/core/scene/pathEffects/effects.js.map +1 -1
  216. package/dist/core/scene/pathEffects/textAlong.js +95 -0
  217. package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
  218. package/dist/core/scene/recorder.js +28 -19
  219. package/dist/core/scene/recorder.js.map +1 -1
  220. package/dist/core/scene/scene.js +15 -9
  221. package/dist/core/scene/scene.js.map +1 -1
  222. package/dist/core/scene/sceneChanges.js +13 -0
  223. package/dist/core/scene/sceneChanges.js.map +1 -0
  224. package/dist/core/scene/sceneEdits.js +8 -1
  225. package/dist/core/scene/sceneEdits.js.map +1 -1
  226. package/dist/core/scene/sceneMutators.js +1 -0
  227. package/dist/core/scene/sceneMutators.js.map +1 -1
  228. package/dist/core/scene/sceneRecording.js +20 -3
  229. package/dist/core/scene/sceneRecording.js.map +1 -1
  230. package/dist/core/scene/sceneSelection.js +4 -1
  231. package/dist/core/scene/sceneSelection.js.map +1 -1
  232. package/dist/core/scene/sceneState.js +11 -5
  233. package/dist/core/scene/sceneState.js.map +1 -1
  234. package/dist/core/scene/serialization.js +5 -3
  235. package/dist/core/scene/serialization.js.map +1 -1
  236. package/dist/core/scene/types.js.map +1 -1
  237. package/dist/core/scene/unitScopes.js +19 -1
  238. package/dist/core/scene/unitScopes.js.map +1 -1
  239. package/dist/core/selection/usePublishSceneSelection.js +6 -12
  240. package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
  241. package/dist/core/shapeKinds.js +25 -11
  242. package/dist/core/shapeKinds.js.map +1 -1
  243. package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-p8fDIAKt.d.ts} +3 -2
  244. package/dist/debug/createDebugOverlayLayer.js +16 -111
  245. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  246. package/dist/debug/createDebugSink.js +2 -1
  247. package/dist/debug/createDebugSink.js.map +1 -1
  248. package/dist/debug/defaultTheme.js +4 -2
  249. package/dist/debug/defaultTheme.js.map +1 -1
  250. package/dist/debug/features.js +17 -0
  251. package/dist/debug/features.js.map +1 -0
  252. package/dist/debug/overlayPanels.js +117 -0
  253. package/dist/debug/overlayPanels.js.map +1 -0
  254. package/dist/debug/parseDebugFlags.js +4 -13
  255. package/dist/debug/parseDebugFlags.js.map +1 -1
  256. package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-mG19aEdD.d.ts} +174 -904
  257. package/dist/devtools/handlers.js +112 -0
  258. package/dist/devtools/handlers.js.map +1 -0
  259. package/dist/devtools/history.js +71 -0
  260. package/dist/devtools/history.js.map +1 -0
  261. package/dist/devtools/hook.js +74 -0
  262. package/dist/devtools/hook.js.map +1 -0
  263. package/dist/devtools/label.js +25 -0
  264. package/dist/devtools/label.js.map +1 -0
  265. package/dist/devtools/notices.js +58 -0
  266. package/dist/devtools/notices.js.map +1 -0
  267. package/dist/devtools/protocol.js +7 -0
  268. package/dist/devtools/protocol.js.map +1 -0
  269. package/dist/devtools/registry.js +90 -0
  270. package/dist/devtools/registry.js.map +1 -0
  271. package/dist/devtools/root.js +80 -0
  272. package/dist/devtools/root.js.map +1 -0
  273. package/dist/devtools/serialize.js +86 -0
  274. package/dist/devtools/serialize.js.map +1 -0
  275. package/dist/devtools/session.js +111 -0
  276. package/dist/devtools/session.js.map +1 -0
  277. package/dist/devtools/transport.js +67 -0
  278. package/dist/devtools/transport.js.map +1 -0
  279. package/dist/devtools/useDevtoolsRoot.js +81 -0
  280. package/dist/devtools/useDevtoolsRoot.js.map +1 -0
  281. package/dist/devtools-protocol.d.ts +435 -0
  282. package/dist/devtools-protocol.js +7 -0
  283. package/dist/devtools.d.ts +8 -0
  284. package/dist/devtools.js +12 -0
  285. package/dist/devtools.js.map +1 -0
  286. package/dist/features/chrome-caps/useHoverTracking.js +16 -10
  287. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  288. package/dist/features/ingestion/contentHandlers.js +25 -2
  289. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  290. package/dist/features/measure/measureCommands.js +7 -5
  291. package/dist/features/measure/measureCommands.js.map +1 -1
  292. package/dist/features/measure/measureContribution.js +4 -2
  293. package/dist/features/measure/measureContribution.js.map +1 -1
  294. package/dist/features/modes/modeTriggers.js +7 -3
  295. package/dist/features/modes/modeTriggers.js.map +1 -1
  296. package/dist/features/pathEffects/effectSources.js +60 -0
  297. package/dist/features/pathEffects/effectSources.js.map +1 -0
  298. package/dist/features/pathEffects/readSource.js +17 -1
  299. package/dist/features/pathEffects/readSource.js.map +1 -1
  300. package/dist/features/pathEffects/textItems.js +53 -0
  301. package/dist/features/pathEffects/textItems.js.map +1 -0
  302. package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
  303. package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
  304. package/dist/features/paths/index.js +2 -2
  305. package/dist/features/paths/pathEditExtension.js.map +1 -1
  306. package/dist/features/paths/pathEditState.js +5 -2
  307. package/dist/features/paths/pathEditState.js.map +1 -1
  308. package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
  309. package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
  310. package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
  311. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
  312. package/dist/features/selection/selectionPose.js +4 -1
  313. package/dist/features/selection/selectionPose.js.map +1 -1
  314. package/dist/features/snap/gather.js +9 -1
  315. package/dist/features/snap/gather.js.map +1 -1
  316. package/dist/features/snap/lazySession.js +17 -0
  317. package/dist/features/snap/lazySession.js.map +1 -0
  318. package/dist/features/snap/marks.js.map +1 -1
  319. package/dist/features/snap/probes2d.js +27 -19
  320. package/dist/features/snap/probes2d.js.map +1 -1
  321. package/dist/features/snap/readoutLayer.js.map +1 -1
  322. package/dist/features/snap/roles.js +2 -1
  323. package/dist/features/snap/roles.js.map +1 -1
  324. package/dist/features/snap/rotationSource.js +25 -8
  325. package/dist/features/snap/rotationSource.js.map +1 -1
  326. package/dist/features/snap/sceneSession2d.js +6 -4
  327. package/dist/features/snap/sceneSession2d.js.map +1 -1
  328. package/dist/features/snap/session2d.js +37 -23
  329. package/dist/features/snap/session2d.js.map +1 -1
  330. package/dist/features/snap/spanSnap.js +5 -2
  331. package/dist/features/snap/spanSnap.js.map +1 -1
  332. package/dist/features/text/sceneTextDrafts.js +65 -0
  333. package/dist/features/text/sceneTextDrafts.js.map +1 -0
  334. package/dist/features/text/textHitAt.js +31 -2
  335. package/dist/features/text/textHitAt.js.map +1 -1
  336. package/dist/features/text/useSceneTextEdit.js +22 -18
  337. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  338. package/dist/features/viewports/aim.js +105 -0
  339. package/dist/features/viewports/aim.js.map +1 -0
  340. package/dist/features/viewports/viewMarker.js +82 -0
  341. package/dist/features/viewports/viewMarker.js.map +1 -0
  342. package/dist/features/viewports/viewMarkerDrag.js +55 -0
  343. package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
  344. package/dist/icons.table.js +1 -1
  345. package/dist/icons.table.js.map +1 -1
  346. package/dist/icons.table.json +0 -10
  347. package/dist/index.d.ts +1198 -894
  348. package/dist/index.js +55 -38
  349. package/dist/interactions/actions/align/action.js +6 -4
  350. package/dist/interactions/actions/align/action.js.map +1 -1
  351. package/dist/interactions/actions/align/align.js.map +1 -1
  352. package/dist/interactions/actions/booleans/action.js +7 -1
  353. package/dist/interactions/actions/booleans/action.js.map +1 -1
  354. package/dist/interactions/actions/booleans/booleans.js +2 -1
  355. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  356. package/dist/interactions/actions/booleans/operands.js +6 -5
  357. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  358. package/dist/interactions/actions/clipboard/action.js +27 -17
  359. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  360. package/dist/interactions/actions/clone/action.js +1 -1
  361. package/dist/interactions/actions/clone/behaviors.js +4 -4
  362. package/dist/interactions/actions/clone/behaviors.js.map +1 -1
  363. package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
  364. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  365. package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
  366. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
  367. package/dist/interactions/actions/defaults/bendSegment.js +8 -5
  368. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
  369. package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
  370. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  371. package/dist/interactions/actions/defaults/contextMenu.js +17 -8
  372. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
  373. package/dist/interactions/actions/defaults/createPaintAction.js +2 -2
  374. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  375. package/dist/interactions/actions/defaults/delete.js +64 -41
  376. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  377. package/dist/interactions/actions/defaults/duplicate.js +12 -9
  378. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  379. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
  380. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  381. package/dist/interactions/actions/defaults/escape.js +11 -8
  382. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  383. package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
  384. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  385. package/dist/interactions/actions/defaults/group.js +21 -15
  386. package/dist/interactions/actions/defaults/group.js.map +1 -1
  387. package/dist/interactions/actions/defaults/ingest.js +17 -9
  388. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  389. package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
  390. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  391. package/dist/interactions/actions/defaults/nudge.js +21 -40
  392. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  393. package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
  394. package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
  395. package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
  396. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  397. package/dist/interactions/actions/defaults/reorder.js +24 -6
  398. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  399. package/dist/interactions/actions/defaults/selectAll.js +8 -5
  400. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  401. package/dist/interactions/actions/defaults/setFill.js +7 -3
  402. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  403. package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
  404. package/dist/interactions/actions/defaults/setStroke.js +12 -11
  405. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  406. package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
  407. package/dist/interactions/actions/defaults/toolActivate.js +7 -1
  408. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  409. package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
  410. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  411. package/dist/interactions/actions/defaults/undoRedo.js +19 -13
  412. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  413. package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
  414. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  415. package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
  416. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  417. package/dist/interactions/actions/distribute/action.js +6 -4
  418. package/dist/interactions/actions/distribute/action.js.map +1 -1
  419. package/dist/interactions/actions/drawnBoxes.js +2 -1
  420. package/dist/interactions/actions/drawnBoxes.js.map +1 -1
  421. package/dist/interactions/actions/edit-anchors/action.js +10 -10
  422. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  423. package/dist/interactions/actions/edit-anchors/preview.js +41 -8
  424. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
  425. package/dist/interactions/actions/flip/action.js +14 -6
  426. package/dist/interactions/actions/flip/action.js.map +1 -1
  427. package/dist/interactions/actions/gestureLifecycle.js +5 -2
  428. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  429. package/dist/interactions/actions/insert/action.js +1 -2
  430. package/dist/interactions/actions/insert/action.js.map +1 -1
  431. package/dist/interactions/actions/insert/commit.js +1 -1
  432. package/dist/interactions/actions/insert/parent.js +11 -0
  433. package/dist/interactions/actions/insert/parent.js.map +1 -0
  434. package/dist/interactions/actions/insert/placeAction.js +7 -2
  435. package/dist/interactions/actions/insert/placeAction.js.map +1 -1
  436. package/dist/interactions/actions/insert/repositionAction.js +2 -1
  437. package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
  438. package/dist/interactions/actions/insert/session.js +5 -1
  439. package/dist/interactions/actions/insert/session.js.map +1 -1
  440. package/dist/interactions/actions/move/action.js +15 -8
  441. package/dist/interactions/actions/move/action.js.map +1 -1
  442. package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
  443. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  444. package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
  445. package/dist/interactions/actions/move/capture.js +1 -1
  446. package/dist/interactions/actions/move/commit/index.js +0 -2
  447. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  448. package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
  449. package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
  450. package/dist/interactions/actions/move/commit/reparent.js +11 -5
  451. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  452. package/dist/interactions/actions/move/frame.js +4 -10
  453. package/dist/interactions/actions/move/frame.js.map +1 -1
  454. package/dist/interactions/actions/move/landedDescendants.js +20 -17
  455. package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
  456. package/dist/interactions/actions/move/layout/container.js +2 -1
  457. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  458. package/dist/interactions/actions/move/layout/dragged.js +1 -1
  459. package/dist/interactions/actions/move/layout/dropPass.js +18 -1
  460. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  461. package/dist/interactions/actions/move/layout/exits.js +5 -5
  462. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  463. package/dist/interactions/actions/move/session.js +14 -3
  464. package/dist/interactions/actions/move/session.js.map +1 -1
  465. package/dist/interactions/actions/move/translate.js +8 -37
  466. package/dist/interactions/actions/move/translate.js.map +1 -1
  467. package/dist/interactions/actions/moveNodes.js +87 -0
  468. package/dist/interactions/actions/moveNodes.js.map +1 -0
  469. package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
  470. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
  471. package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
  472. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
  473. package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
  474. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
  475. package/dist/interactions/actions/planeInput.js.map +1 -1
  476. package/dist/interactions/actions/resize/action.js +83 -72
  477. package/dist/interactions/actions/resize/action.js.map +1 -1
  478. package/dist/interactions/actions/resize/commit.js +2 -1
  479. package/dist/interactions/actions/resize/commit.js.map +1 -1
  480. package/dist/interactions/actions/resize/cornerHandles.js +2 -1
  481. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
  482. package/dist/interactions/actions/resize/session.js +2 -0
  483. package/dist/interactions/actions/resize/session.js.map +1 -1
  484. package/dist/interactions/actions/resolvePreviews.js +3 -3
  485. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  486. package/dist/interactions/actions/rotate/action.js +7 -4
  487. package/dist/interactions/actions/rotate/action.js.map +1 -1
  488. package/dist/interactions/actions/rotate/commit.js +2 -1
  489. package/dist/interactions/actions/rotate/commit.js.map +1 -1
  490. package/dist/interactions/actions/rotate/session.js +2 -0
  491. package/dist/interactions/actions/rotate/session.js.map +1 -1
  492. package/dist/interactions/actions/selectionSubtree.js +25 -9
  493. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  494. package/dist/interactions/actions/testUtils.js.map +1 -1
  495. package/dist/interactions/actions/transform-again/action.js +13 -11
  496. package/dist/interactions/actions/transform-again/action.js.map +1 -1
  497. package/dist/interactions/actions/transformFinish.js +106 -0
  498. package/dist/interactions/actions/transformFinish.js.map +1 -0
  499. package/dist/json.d.ts +4 -0
  500. package/dist/json.js +3 -0
  501. package/dist/kitSettingsSchema.js +8 -5
  502. package/dist/kitSettingsSchema.js.map +1 -1
  503. package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
  504. package/dist/math.d.ts +1 -1
  505. package/dist/math.js +2 -1
  506. package/dist/move.d.ts +5 -4
  507. package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
  508. package/dist/resize.d.ts +4 -3
  509. package/dist/routing.d.ts +1 -1
  510. package/dist/routing.js +2 -2
  511. package/dist/test-hook/createTestHook.js +1 -1
  512. package/dist/test-hook/createTestHook.js.map +1 -1
  513. package/dist/test-hook/useTestHook.js +2 -1
  514. package/dist/test-hook/useTestHook.js.map +1 -1
  515. package/dist/test-seams.d.ts +9 -5
  516. package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
  517. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  518. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
  519. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  520. package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
  521. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
  522. package/dist/tools/builtin/hand/useHandTool.js +7 -4
  523. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  524. package/dist/tools/builtin/image/useImageTool.js +1 -0
  525. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  526. package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
  527. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  528. package/dist/tools/builtin/line/useLineTool.js +1 -0
  529. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  530. package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
  531. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
  532. package/dist/tools/builtin/pen/penHandle.js +3 -5
  533. package/dist/tools/builtin/pen/penHandle.js.map +1 -1
  534. package/dist/tools/builtin/pen/usePenTool.js +14 -6
  535. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  536. package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
  537. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  538. package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
  539. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  540. package/dist/tools/builtin/rect/useRectTool.js +1 -0
  541. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  542. package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
  543. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  544. package/dist/tools/builtin/select/pressDecision.js +32 -0
  545. package/dist/tools/builtin/select/pressDecision.js.map +1 -0
  546. package/dist/tools/builtin/select/selectionContributions.js +22 -13
  547. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  548. package/dist/tools/builtin/select/useSelectTool.js +13 -10
  549. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  550. package/dist/tools/builtin/slice/useSliceTool.js +22 -8
  551. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  552. package/dist/tools/builtin/star/useStarTool.js +13 -4
  553. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  554. package/dist/tools/builtin/sticky/stickyNode.js +4 -1
  555. package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
  556. package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
  557. package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
  558. package/dist/tools/builtin/text/useTextTool.js +3 -1
  559. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  560. package/dist/tools/index.js +26 -0
  561. package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
  562. package/dist/types-BN9hbdMI.d.ts +184 -0
  563. package/dist/types-CniVctmk.d.ts +949 -0
  564. package/dist/types-oFeQ5VjV.d.ts +264 -0
  565. package/dist/util/paint.js +1 -3
  566. package/dist/util/paint.js.map +1 -1
  567. package/dist/version.js +1 -1
  568. package/package.json +39 -25
  569. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
  570. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
  571. package/dist/tools/builtin/bone/boneActions.js +0 -156
  572. package/dist/tools/builtin/bone/boneActions.js.map +0 -1
  573. package/dist/tools/builtin/bone/boneOverlay.js +0 -71
  574. package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
  575. package/dist/tools/builtin/bone/placedRig.js +0 -28
  576. package/dist/tools/builtin/bone/placedRig.js.map +0 -1
  577. package/dist/tools/builtin/bone/rigEditState.js +0 -30
  578. package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
  579. package/dist/tools/builtin/bone/useBoneTool.js +0 -125
  580. package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
  581. package/dist/tools/builtin/weight/useWeightTool.js +0 -101
  582. package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
  583. package/dist/tools/builtin/weight/weightActions.js +0 -140
  584. package/dist/tools/builtin/weight/weightActions.js.map +0 -1
  585. package/dist/tools/builtin/weight/weightOverlay.js +0 -78
  586. package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
@@ -7,45 +7,55 @@
7
7
  var SHAPE_KINDS = {
8
8
  rect: {
9
9
  tool: true,
10
- insertPreview: true
10
+ insertPreview: true,
11
+ family: "shape"
11
12
  },
12
13
  ellipse: {
13
14
  tool: true,
14
- insertPreview: true
15
+ insertPreview: true,
16
+ family: "shape"
15
17
  },
16
18
  line: {
17
19
  tool: true,
18
- insertPreview: true
20
+ insertPreview: true,
21
+ family: "shape"
19
22
  },
20
23
  polygon: {
21
24
  tool: true,
22
- insertPreview: true
25
+ insertPreview: true,
26
+ family: "shape"
23
27
  },
24
28
  star: {
25
29
  tool: true,
26
- insertPreview: true
30
+ insertPreview: true,
31
+ family: "shape"
27
32
  },
28
33
  pen: {
29
34
  tool: true,
30
- insertPreview: false
35
+ insertPreview: false,
36
+ family: "draw"
31
37
  },
32
38
  pencil: {
33
39
  tool: true,
34
- insertPreview: true
40
+ insertPreview: true,
41
+ family: "draw"
35
42
  },
36
43
  lasso: {
37
44
  tool: true,
38
- insertPreview: false
45
+ insertPreview: false,
46
+ family: "select"
39
47
  },
40
48
  text: {
41
49
  tool: true,
42
50
  insertPreview: true,
43
- text: true
51
+ text: true,
52
+ family: "type"
44
53
  },
45
54
  sticky: {
46
55
  tool: true,
47
56
  insertPreview: true,
48
- text: true
57
+ text: true,
58
+ family: "type"
49
59
  },
50
60
  image: {
51
61
  tool: false,
@@ -63,7 +73,11 @@ function shapeKindInfo(kind) {
63
73
  }
64
74
  /** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`. */
65
75
  var KIT_SHAPE_KINDS = shapeKindsWhere(SHAPE_KINDS, "tool");
76
+ /** The shape-tool ids of one family, in declaration order. */
77
+ function kitShapeKindsOf(family) {
78
+ return KIT_SHAPE_KINDS.filter((k) => SHAPE_KINDS[k].family === family);
79
+ }
66
80
 
67
81
  //#endregion
68
- export { KIT_SHAPE_KINDS, SHAPE_KINDS, shapeKindInfo, shapeKindsWhere };
82
+ export { KIT_SHAPE_KINDS, SHAPE_KINDS, kitShapeKindsOf, shapeKindInfo, shapeKindsWhere };
69
83
  //# sourceMappingURL=shapeKinds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shapeKinds.js","names":[],"sources":["../../src/core/shapeKinds.ts"],"sourcesContent":["/**\n * The kit's built-in shape kinds — one table, every other spelling derived.\n *\n * This module imports nothing on purpose: `useBuiltinShapeTools` imports the\n * package barrel, so anything barrel-reachable that needs these lists at\n * module-evaluation time must not route through it.\n */\n\n/** What the kit knows about one built-in shape kind. */\nexport interface ShapeKindDescriptor {\n /** Mounted as a built-in shape tool by `useBuiltinShapeTools`, and so a\n * member of `BuiltinShapeToolId` / `KIT_SHAPE_KINDS`. `image` is false:\n * `useImageTool` needs a `src` and can't be auto-mounted. */\n readonly tool: boolean;\n /** `insertAction` emits an `insertPreview` overlay for this kind, and the\n * dispatcher overlay layer knows how to draw it. Kinds without one still\n * commit; they just have no live drag preview. */\n readonly insertPreview: boolean;\n /** A node of this kind is a text node: an insert drops into its caret, and\n * its properties carry the text groups. Absent, it is not. */\n readonly text?: boolean;\n}\n\n/**\n * Declaration order is the enumeration order of every derived list —\n * `KIT_SHAPE_KINDS`, and through it `defaultNodeRouting` /\n * `defaultNodeProperties` / `BUILTIN_TOOL_IDS`.\n */\nexport const SHAPE_KINDS = {\n rect: { tool: true, insertPreview: true },\n ellipse: { tool: true, insertPreview: true },\n line: { tool: true, insertPreview: true },\n polygon: { tool: true, insertPreview: true },\n star: { tool: true, insertPreview: true },\n pen: { tool: true, insertPreview: false },\n pencil: { tool: true, insertPreview: true },\n lasso: { tool: true, insertPreview: false },\n text: { tool: true, insertPreview: true, text: true },\n sticky: { tool: true, insertPreview: true, text: true },\n image: { tool: false, insertPreview: true },\n} as const satisfies Record<string, ShapeKindDescriptor>;\n\n/** Every kind in the table, tool or not. */\nexport type ShapeKind = keyof typeof SHAPE_KINDS;\n\n/** The keys of a shape-kind table whose descriptor sets `F` to `true`. */\nexport type ShapeKindsWhere<T, F extends keyof ShapeKindDescriptor> = {\n [K in keyof T]: T[K] extends Record<F, true> ? K : never;\n}[keyof T];\n\n/** Built-in shape tool ids handled by `useBuiltinShapeTools`. */\nexport type BuiltinShapeToolId = ShapeKindsWhere<typeof SHAPE_KINDS, 'tool'>;\n\n/** The insert kinds the kit's dispatcher overlay layer knows how to render.\n * Consumer-defined kinds fall outside it: no live preview, commit unaffected. */\nexport type KitInsertShape = ShapeKindsWhere<typeof SHAPE_KINDS, 'insertPreview'>;\n\n/** Kinds in `table` whose descriptor sets `field`, in declaration order. */\nexport function shapeKindsWhere<T extends Record<string, ShapeKindDescriptor>>(\n table: T,\n field: keyof ShapeKindDescriptor,\n): (keyof T & string)[] {\n return (Object.keys(table) as (keyof T & string)[]).filter((k) => table[k][field]);\n}\n\n/** The descriptor for `kind`, or `undefined` for a kind the kit doesn't ship.\n * The one accessor: ask it rather than testing membership of a derived list. */\nexport function shapeKindInfo(kind: string): ShapeKindDescriptor | undefined {\n return (SHAPE_KINDS as Record<string, ShapeKindDescriptor>)[kind];\n}\n\n/** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`. */\nexport const KIT_SHAPE_KINDS: readonly BuiltinShapeToolId[] =\n shapeKindsWhere(SHAPE_KINDS, 'tool') as BuiltinShapeToolId[];\n"],"mappings":";;;;;;AA4BA,IAAa,cAAc;CACzB,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,KAAK;EAAE,MAAM;EAAM,eAAe;CAAM;CACxC,QAAQ;EAAE,MAAM;EAAM,eAAe;CAAK;CAC1C,OAAO;EAAE,MAAM;EAAM,eAAe;CAAM;CAC1C,MAAM;EAAE,MAAM;EAAM,eAAe;EAAM,MAAM;CAAK;CACpD,QAAQ;EAAE,MAAM;EAAM,eAAe;EAAM,MAAM;CAAK;CACtD,OAAO;EAAE,MAAM;EAAO,eAAe;CAAK;AAC5C;;AAkBA,SAAgB,gBACd,OACA,OACsB;CACtB,OAAQ,OAAO,KAAK,KAAK,CAAC,CAA0B,QAAQ,MAAM,MAAM,EAAE,CAAC,MAAM;AACnF;;;AAIA,SAAgB,cAAc,MAA+C;CAC3E,OAAQ,YAAoD;AAC9D;;AAGA,IAAa,kBACX,gBAAgB,aAAa,MAAM"}
1
+ {"version":3,"file":"shapeKinds.js","names":[],"sources":["../../src/core/shapeKinds.ts"],"sourcesContent":["/**\n * The kit's built-in shape kinds — one table, every other spelling derived.\n *\n * This module imports nothing on purpose: `useBuiltinShapeTools` imports the\n * package barrel, so anything barrel-reachable that needs these lists at\n * module-evaluation time must not route through it.\n */\n\n/** What the kit knows about one built-in shape kind. */\nexport interface ShapeKindDescriptor {\n /** Mounted as a built-in shape tool by `useBuiltinShapeTools`, and so a\n * member of `BuiltinShapeToolId` / `KIT_SHAPE_KINDS`. `image` is false:\n * `useImageTool` needs a `src` and can't be auto-mounted. */\n readonly tool: boolean;\n /** `insertAction` emits an `insertPreview` overlay for this kind, and the\n * dispatcher overlay layer knows how to draw it. Kinds without one still\n * commit; they just have no live drag preview. */\n readonly insertPreview: boolean;\n /** The tool family a kind with a tool belongs to: which built-in tool set\n * names it, and so which palette group it sits in. */\n readonly family?: 'shape' | 'draw' | 'select' | 'type';\n /** A node of this kind is a text node: an insert drops into its caret, and\n * its properties carry the text groups. Absent, it is not. */\n readonly text?: boolean;\n}\n\n/**\n * Declaration order is the enumeration order of every derived list —\n * `KIT_SHAPE_KINDS`, and through it `defaultNodeRouting` /\n * `defaultNodeProperties` / `BUILTIN_TOOL_IDS`.\n */\nexport const SHAPE_KINDS = {\n rect: { tool: true, insertPreview: true, family: 'shape' },\n ellipse: { tool: true, insertPreview: true, family: 'shape' },\n line: { tool: true, insertPreview: true, family: 'shape' },\n polygon: { tool: true, insertPreview: true, family: 'shape' },\n star: { tool: true, insertPreview: true, family: 'shape' },\n pen: { tool: true, insertPreview: false, family: 'draw' },\n pencil: { tool: true, insertPreview: true, family: 'draw' },\n lasso: { tool: true, insertPreview: false, family: 'select' },\n text: { tool: true, insertPreview: true, text: true, family: 'type' },\n sticky: { tool: true, insertPreview: true, text: true, family: 'type' },\n image: { tool: false, insertPreview: true },\n} as const satisfies Record<string, ShapeKindDescriptor>;\n\n/** Every kind in the table, tool or not. */\nexport type ShapeKind = keyof typeof SHAPE_KINDS;\n\n/** The keys of a shape-kind table whose descriptor sets `F` to `true`. */\nexport type ShapeKindsWhere<T, F extends keyof ShapeKindDescriptor> = {\n [K in keyof T]: T[K] extends Record<F, true> ? K : never;\n}[keyof T];\n\n/** Built-in shape tool ids handled by `useBuiltinShapeTools`. */\nexport type BuiltinShapeToolId = ShapeKindsWhere<typeof SHAPE_KINDS, 'tool'>;\n\n/** The insert kinds the kit's dispatcher overlay layer knows how to render.\n * Consumer-defined kinds fall outside it: no live preview, commit unaffected. */\nexport type KitInsertShape = ShapeKindsWhere<typeof SHAPE_KINDS, 'insertPreview'>;\n\n/** Kinds in `table` whose descriptor sets `field`, in declaration order. */\nexport function shapeKindsWhere<T extends Record<string, ShapeKindDescriptor>>(\n table: T,\n field: keyof ShapeKindDescriptor,\n): (keyof T & string)[] {\n return (Object.keys(table) as (keyof T & string)[]).filter((k) => table[k][field]);\n}\n\n/** The descriptor for `kind`, or `undefined` for a kind the kit doesn't ship.\n * The one accessor: ask it rather than testing membership of a derived list. */\nexport function shapeKindInfo(kind: string): ShapeKindDescriptor | undefined {\n return (SHAPE_KINDS as Record<string, ShapeKindDescriptor>)[kind];\n}\n\n/** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`. */\nexport const KIT_SHAPE_KINDS: readonly BuiltinShapeToolId[] =\n shapeKindsWhere(SHAPE_KINDS, 'tool') as BuiltinShapeToolId[];\n\n/** The shape-tool ids of one family, in declaration order. */\nexport function kitShapeKindsOf(family: NonNullable<ShapeKindDescriptor['family']>): BuiltinShapeToolId[] {\n return KIT_SHAPE_KINDS.filter((k) => (SHAPE_KINDS as Record<string, ShapeKindDescriptor>)[k]!.family === family);\n}\n"],"mappings":";;;;;;AA+BA,IAAa,cAAc;CACzB,MAAM;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAQ;CACzD,SAAS;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAQ;CAC5D,MAAM;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAQ;CACzD,SAAS;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAQ;CAC5D,MAAM;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAQ;CACzD,KAAK;EAAE,MAAM;EAAM,eAAe;EAAO,QAAQ;CAAO;CACxD,QAAQ;EAAE,MAAM;EAAM,eAAe;EAAM,QAAQ;CAAO;CAC1D,OAAO;EAAE,MAAM;EAAM,eAAe;EAAO,QAAQ;CAAS;CAC5D,MAAM;EAAE,MAAM;EAAM,eAAe;EAAM,MAAM;EAAM,QAAQ;CAAO;CACpE,QAAQ;EAAE,MAAM;EAAM,eAAe;EAAM,MAAM;EAAM,QAAQ;CAAO;CACtE,OAAO;EAAE,MAAM;EAAO,eAAe;CAAK;AAC5C;;AAkBA,SAAgB,gBACd,OACA,OACsB;CACtB,OAAQ,OAAO,KAAK,KAAK,CAAC,CAA0B,QAAQ,MAAM,MAAM,EAAE,CAAC,MAAM;AACnF;;;AAIA,SAAgB,cAAc,MAA+C;CAC3E,OAAQ,YAAoD;AAC9D;;AAGA,IAAa,kBACX,gBAAgB,aAAa,MAAM;;AAGrC,SAAgB,gBAAgB,QAA0E;CACxG,OAAO,gBAAgB,QAAQ,MAAO,YAAoD,EAAE,CAAE,WAAW,MAAM;AACjH"}
@@ -1,4 +1,4 @@
1
- import { B as BoundsConstraint } from './clone-DZDrfIlU.js';
1
+ import { B as BoundsConstraint } from './clone-C3e0OTuF.js';
2
2
  import { FramedBox, Affine } from '@weasel-js/geom';
3
3
  import { ResizeAnchor } from '@weasel-js/routing';
4
4
 
@@ -139,7 +139,8 @@ declare function handlePoint(bounds: FramedBox, entry: Pick<ResizeHandleAnchor,
139
139
  x: number;
140
140
  y: number;
141
141
  };
142
- /** @deprecated Use {@link handlePoint}, which also places edge handles. */
142
+ /** A corner handle's position for the given bounds, in the bounds' frame.
143
+ * @deprecated Use {@link handlePoint}, which also places edge handles. */
143
144
  declare const cornerPoint: (bounds: FramedBox, entry: Pick<CornerAnchor, 'xEdge' | 'yEdge'>) => {
144
145
  x: number;
145
146
  y: number;
@@ -2,6 +2,7 @@ import { viewToTransform } from "../core/viewport/view.js";
2
2
  import { worldToScreen } from "../core/viewport/viewTransform.js";
3
3
  import { rotatePoint } from "../interactions/actions/rotate/geometry.js";
4
4
  import { DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME } from "./defaultTheme.js";
5
+ import { LINE_H, emitFramePanel, emitLayersPanel, emitTextPanel, rectPath as rectPath$1 } from "./overlayPanels.js";
5
6
  import { textCommandFromRuns } from "@weasel-js/renderer";
6
7
  import { PATH_L, PATH_M, PATH_Z } from "@weasel-js/geom";
7
8
 
@@ -53,6 +54,7 @@ function buildDebugOverlayCommands(snapshot, config, view, dims, frameTimes = []
53
54
  if (config.viewport && s.viewport) emitViewport(out, s.viewport, view, dims, theme, strokes);
54
55
  if (config.hitboxes) emitHitboxes(out, s, view, t, theme, strokes);
55
56
  if (config.bounds) emitBounds(out, s, view, t, theme, strokes);
57
+ if (config.highlight?.length) emitHighlight(out, s, new Set(config.highlight), view, t, theme, strokes);
56
58
  if (config.handles) emitHandles(out, s, t, theme, strokes);
57
59
  if (config.origins) emitOrigins(out, s, t, theme);
58
60
  if (config.snap) emitSnap(out, s, t, theme, strokes);
@@ -113,17 +115,6 @@ function rotatedRectScreen(r, t) {
113
115
  fillRule: "nonzero"
114
116
  };
115
117
  }
116
- function rectPath$1(x, y, w, h) {
117
- return {
118
- kind: "rect",
119
- x,
120
- y,
121
- width: w,
122
- height: h
123
- };
124
- }
125
- /** A `DebugStroke` + color as the renderer's stroke shape. `dash` is dropped
126
- * when empty rather than passed through, so a solid line stays solid. */
127
118
  function strokeOf(s, color) {
128
119
  return {
129
120
  paint: {
@@ -208,6 +199,18 @@ function emitBounds(out, s, view, t, theme, strokes) {
208
199
  });
209
200
  }
210
201
  }
202
+ function emitHighlight(out, s, ids, view, t, theme, strokes) {
203
+ const stroke = strokeOf(strokes.highlight, theme.highlight);
204
+ for (const b of s.bounds) {
205
+ if (!ids.has(b.id)) continue;
206
+ const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);
207
+ out.push({
208
+ kind: "path",
209
+ path: rectPath$1(sx, sy, b.bounds.width * view.scale.x, b.bounds.height * view.scale.y),
210
+ stroke
211
+ });
212
+ }
213
+ }
211
214
  function emitHandles(out, s, t, theme, strokes) {
212
215
  const stroke = strokeOf(strokes.handle, theme.handle);
213
216
  for (const h of s.handles) {
@@ -290,105 +293,6 @@ function emitIds(out, s, t, theme) {
290
293
  }));
291
294
  }
292
295
  }
293
- function emitLayersPanel(out, s, dims, theme) {
294
- if (s.layers.length === 0) return;
295
- const lineH = 14;
296
- const padX = 6;
297
- const lines = s.layers.map((l) => `[${l.index}] ${l.id} (${l.space})`);
298
- const charW = 6.6;
299
- let maxW = 0;
300
- for (const line of lines) maxW = Math.max(maxW, line.length * charW);
301
- const boxW = maxW + 12;
302
- const boxH = lines.length * lineH + 8;
303
- const x = dims.width - boxW - 8;
304
- out.push({
305
- kind: "path",
306
- path: rectPath$1(x, 8, boxW, boxH),
307
- fill: { paint: {
308
- kind: "solid",
309
- color: theme.layerTextBg
310
- } }
311
- });
312
- for (let i = 0; i < lines.length; i++) out.push(textCommandFromRuns(x + padX, 12 + i * lineH, [{
313
- text: lines[i],
314
- fill: { paint: {
315
- kind: "solid",
316
- color: theme.layerText
317
- } }
318
- }], {
319
- fontFamily: "ui-monospace, Menlo, monospace",
320
- fontSize: 11
321
- }));
322
- }
323
- var MONO = {
324
- fontFamily: "ui-monospace, Menlo, monospace",
325
- fontSize: 11
326
- };
327
- var MONO_CHAR_W = 6.6;
328
- var LINE_H = 14;
329
- /** A dark box holding monospace lines, at `(x, y)`; `y < 0` anchors its bottom
330
- * that far above `bottom`. Width is estimated from the character count — there
331
- * is no text measurer here, and a debug panel does not need one. */
332
- function emitTextPanel(out, lines, x, y, color, bg) {
333
- const padX = 6;
334
- const padY = 4;
335
- let maxLen = 0;
336
- for (const l of lines) maxLen = Math.max(maxLen, l.length);
337
- out.push({
338
- kind: "path",
339
- path: rectPath$1(x, y, maxLen * MONO_CHAR_W + 12, lines.length * LINE_H + 8),
340
- fill: { paint: {
341
- kind: "solid",
342
- color: bg
343
- } }
344
- });
345
- for (let i = 0; i < lines.length; i++) out.push(textCommandFromRuns(x + padX, y + padY + i * LINE_H, [{
346
- text: lines[i],
347
- fill: { paint: {
348
- kind: "solid",
349
- color
350
- } }
351
- }], MONO));
352
- }
353
- /** Fixed-width number, right-aligned, `decimals` places: `%{width}.{decimals}f`. */
354
- function fixed(v, width, decimals) {
355
- return v.toFixed(decimals).padStart(width);
356
- }
357
- function emitFramePanel(out, history, frame, theme) {
358
- const span = history.length >= 2 ? history[history.length - 1] - history[0] : 0;
359
- const interval = span > 0 ? span / (history.length - 1) : null;
360
- const rows = [[
361
- "fps",
362
- null,
363
- interval ? 1e3 / interval : null,
364
- " "
365
- ], [
366
- "frame",
367
- null,
368
- interval,
369
- "ms"
370
- ]];
371
- if (frame) {
372
- rows.push([
373
- "paint",
374
- frame.drawCalls,
375
- frame.paintMs,
376
- "ms"
377
- ]);
378
- for (const l of frame.layers) rows.push([
379
- l.id,
380
- l.drawCalls,
381
- l.ms,
382
- "ms"
383
- ]);
384
- }
385
- let labelW = 0;
386
- for (const [label] of rows) labelW = Math.max(labelW, label.length);
387
- const line = (label, count, value, unit) => `${label.padEnd(labelW)} ${count.padStart(5)} ${value.padStart(7)} ${unit}`;
388
- const lines = rows.map(([label, count, value, unit]) => line(label, count === null ? "" : String(count), value === null ? "—" : fixed(value, 7, 2), unit));
389
- if (frame) lines.splice(2, 0, line("", "draws", "cpu", " "));
390
- emitTextPanel(out, lines, 8, 8, theme.fpsText, theme.fpsTextBg);
391
- }
392
296
  function emitViewport(out, rec, view, dims, theme, strokes) {
393
297
  const t = viewToTransform(view);
394
298
  const stroke = strokeOf(strokes.viewport, theme.viewport);
@@ -421,7 +325,8 @@ function emitViewport(out, rec, view, dims, theme, strokes) {
421
325
  stroke: strokeOf({ width: strokes.viewport.width }, theme.viewport)
422
326
  });
423
327
  }
424
- emitTextPanel(out, [rec.kind === "pan" ? `pan Δ ${signed((from.x - to.x) * to.scale.x)} ${signed((from.y - to.y) * to.scale.y)} px` : `zoom ×${(to.scale.x / from.scale.x).toFixed(3)} ${from.scale.x.toFixed(3)} → ${to.scale.x.toFixed(3)}`], 8, dims.height - LINE_H - 16, theme.viewport, theme.layerTextBg);
328
+ const text = rec.kind === "pan" ? `pan Δ ${signed((from.x - to.x) * to.scale.x)} ${signed((from.y - to.y) * to.scale.y)} px` : `zoom ×${(to.scale.x / from.scale.x).toFixed(3)} ${from.scale.x.toFixed(3)} → ${to.scale.x.toFixed(3)}`;
329
+ emitTextPanel(out, [text], 8, dims.height - LINE_H - 16, theme.viewport, theme.layerTextBg);
425
330
  }
426
331
  function signed(v) {
427
332
  const r = Math.abs(v) < .05 ? 0 : v;
@@ -1 +1 @@
1
- {"version":3,"file":"createDebugOverlayLayer.js","names":["rectPath"],"sources":["../../src/debug/createDebugOverlayLayer.ts"],"sourcesContent":["import type { DrawCommand, PathDrawCommand } from '@weasel-js/renderer';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport type { View } from 'core/viewport/view';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\nimport { rotatePoint } from 'interactions/actions/rotate/geometry';\nimport { PATH_L, PATH_M, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport { textCommandFromRuns } from '@weasel-js/renderer';\nimport type {\n DebugConfig,\n DebugSnapshot,\n DebugStroke,\n DebugStrokes,\n DebugTheme,\n FrameStats,\n RecordedViewport,\n} from './types';\nimport { DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME } from './defaultTheme';\n\n/** What `createDebugOverlayLayer` paints from: a sink to snapshot and the features to draw. */\nexport interface CreateDebugOverlayLayerOpts {\n sink: { snapshot(): DebugSnapshot };\n config: DebugConfig;\n}\n\nexport const DEBUG_OVERLAY_ID = 'debug-overlay';\nconst FPS_WINDOW = 60;\n\n/**\n * Screen-space `RenderLayer` that paints the sink's snapshot. Appended at\n * the top of the Canvas's layer stack when `debug` is enabled. World-space\n * coords in the snapshot are projected through `view` here, since the\n * layer itself runs at identity transform.\n */\nexport function createDebugOverlayLayer({\n sink,\n config,\n}: CreateDebugOverlayLayerOpts): RenderLayer<unknown> {\n // Timestamps of the last FPS_WINDOW draws, kept for the life of the layer.\n const fpsHistory: number[] = [];\n return {\n id: DEBUG_OVERLAY_ID,\n label: 'Debug overlay',\n space: 'screen',\n alwaysOn: true,\n draw: (_data, view, dims) => {\n if (config.fps) {\n fpsHistory.push(typeof performance !== 'undefined' ? performance.now() : Date.now());\n if (fpsHistory.length > FPS_WINDOW) fpsHistory.shift();\n } else if (fpsHistory.length > 0) {\n fpsHistory.length = 0;\n }\n return buildDebugOverlayCommands(sink.snapshot(), config, view, dims, fpsHistory);\n },\n };\n}\n\n/**\n * The debug overlay's draw commands for one snapshot, in screen space (CSS\n * pixels of a `dims`-sized canvas looking through `view`). What the overlay\n * layer paints each frame, and what `renderDebugSnapshot` rasterizes.\n *\n * `frameTimes` are `performance.now()` stamps of recent paints, oldest first;\n * the frame panel derives its rate from them and shows none without two.\n */\nexport function buildDebugOverlayCommands(\n snapshot: DebugSnapshot,\n config: DebugConfig,\n view: View,\n dims: Dims,\n frameTimes: readonly number[] = [],\n): DrawCommand[] {\n const theme: DebugTheme = { ...DEFAULT_DEBUG_THEME, ...(config.theme ?? {}) };\n const strokes: DebugStrokes = { ...DEFAULT_DEBUG_STROKES, ...(config.strokes ?? {}) };\n const s = snapshot;\n const t = viewToTransform(view);\n const out: DrawCommand[] = [];\n\n if (config.viewport && s.viewport) emitViewport(out, s.viewport, view, dims, theme, strokes);\n if (config.hitboxes) emitHitboxes(out, s, view, t, theme, strokes);\n if (config.bounds) emitBounds(out, s, view, t, theme, strokes);\n if (config.handles) emitHandles(out, s, t, theme, strokes);\n if (config.origins) emitOrigins(out, s, t, theme);\n if (config.snap) emitSnap(out, s, t, theme, strokes);\n if (config.ids) emitIds(out, s, t, theme);\n if (config.layers) emitLayersPanel(out, s, dims, theme);\n if (config.fps) emitFramePanel(out, frameTimes, s.frame, theme);\n return out;\n}\n\n// --- emitters (screen-space) ---\n\nfunction approxCircleScreen(cx: number, cy: number, r: number, segments = 24): PolygonPath {\n return approxEllipseScreen(cx, cy, r, r, segments);\n}\n\nfunction approxEllipseScreen(cx: number, cy: number, rx: number, ry: number, segments = 24): PolygonPath {\n // Commands: M + (segments-1) L + Z. Coords: (segments) × 2 — pairs for\n // the moveTo and the (segments-1) lineTos. PATH_Z consumes no coords.\n const cmds = new Uint8Array(segments + 1);\n const coords = new Float32Array(segments * 2);\n cmds[0] = PATH_M;\n coords[0] = cx + rx;\n coords[1] = cy;\n for (let i = 1; i < segments; i++) {\n cmds[i] = PATH_L;\n const theta = (i / segments) * Math.PI * 2;\n coords[i * 2] = cx + rx * Math.cos(theta);\n coords[i * 2 + 1] = cy + ry * Math.sin(theta);\n }\n cmds[segments] = PATH_Z;\n return { kind: 'polygon', commands: cmds, coords, fillRule: 'nonzero' };\n}\n\n/** A world rect turned `rotation` about its center, as the screen quad it\n * lands on. */\nfunction rotatedRectScreen(\n r: { x: number; y: number; width: number; height: number; rotation: number },\n t: ReturnType<typeof viewToTransform>,\n): PolygonPath {\n const cx = r.x + r.width / 2, cy = r.y + r.height / 2;\n const coords = new Float32Array(8);\n const corners = [[r.x, r.y], [r.x + r.width, r.y], [r.x + r.width, r.y + r.height], [r.x, r.y + r.height]];\n corners.forEach(([x, y], i) => {\n const w = rotatePoint(x, y, cx, cy, r.rotation);\n const [sx, sy] = worldToScreen(w.x, w.y, t);\n coords[i * 2] = sx;\n coords[i * 2 + 1] = sy;\n });\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),\n coords,\n fillRule: 'nonzero',\n };\n}\n\nfunction rectPath(x: number, y: number, w: number, h: number): { kind: 'rect'; x: number; y: number; width: number; height: number } {\n return { kind: 'rect', x, y, width: w, height: h };\n}\n\n/** A `DebugStroke` + color as the renderer's stroke shape. `dash` is dropped\n * when empty rather than passed through, so a solid line stays solid. */\nfunction strokeOf(s: DebugStroke, color: string) {\n return {\n paint: { kind: 'solid' as const, color },\n width: s.width,\n ...(s.dash && s.dash.length > 0 ? { dash: [...s.dash] } : {}),\n };\n}\n\nfunction emitHitboxes(\n out: DrawCommand[],\n s: DebugSnapshot,\n view: View,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const fill = { kind: 'solid' as const, color: theme.hitboxFill };\n const stroke = strokeOf(strokes.hitbox, theme.hitboxStroke);\n for (const h of s.hitboxes) {\n if (h.shape.kind === 'rect' && h.shape.rotation) {\n const path = rotatedRectScreen({ ...h.shape, rotation: h.shape.rotation }, t);\n out.push({ kind: 'path', path, fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'rect') {\n const [sx, sy] = worldToScreen(h.shape.x, h.shape.y, t);\n const sw = h.shape.width * view.scale.x;\n const sh = h.shape.height * view.scale.y;\n out.push({ kind: 'path', path: rectPath(sx, sy, sw, sh), fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'circle') {\n const [cx, cy] = worldToScreen(h.shape.cx, h.shape.cy, t);\n const rx = h.shape.r * Math.abs(view.scale.x);\n const ry = h.shape.r * Math.abs(view.scale.y);\n out.push({ kind: 'path', path: approxEllipseScreen(cx, cy, rx, ry), fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'polygon' && h.shape.points.length > 2) {\n const pts = h.shape.points;\n const coords = new Float32Array(pts.length * 2);\n pts.forEach((p, i) => {\n const [sx, sy] = worldToScreen(p.x, p.y, t);\n coords[i * 2] = sx;\n coords[i * 2 + 1] = sy;\n });\n const commands = new Uint8Array(pts.length + 1).fill(PATH_L);\n commands[0] = PATH_M;\n commands[pts.length] = PATH_Z;\n out.push({ kind: 'path', path: { kind: 'polygon', commands, coords, fillRule: 'nonzero' }, fill: { paint: fill }, stroke });\n }\n // 'path' kind: v1 punt — matches 2D behavior.\n }\n}\n\nfunction emitBounds(\n out: DrawCommand[],\n s: DebugSnapshot,\n view: View,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const stroke = strokeOf(strokes.bounds, theme.bounds);\n for (const b of s.bounds) {\n const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);\n const sw = b.bounds.width * view.scale.x;\n const sh = b.bounds.height * view.scale.y;\n out.push({ kind: 'path', path: rectPath(sx, sy, sw, sh), stroke });\n }\n}\n\nfunction emitHandles(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const stroke = strokeOf(strokes.handle, theme.handle);\n for (const h of s.handles) {\n const [cx, cy] = worldToScreen(h.position.x, h.position.y, t);\n const horiz: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([cx - 4, cy, cx + 4, cy]),\n fillRule: 'nonzero',\n };\n const vert: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([cx, cy - 4, cx, cy + 4]),\n fillRule: 'nonzero',\n };\n out.push({ kind: 'path', path: horiz, stroke });\n out.push({ kind: 'path', path: vert, stroke });\n }\n}\n\nfunction emitOrigins(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n): void {\n const fill = { kind: 'solid' as const, color: theme.origin };\n for (const o of s.origins) {\n const [cx, cy] = worldToScreen(o.point.x, o.point.y, t);\n out.push({ kind: 'path', path: approxCircleScreen(cx, cy, 3), fill: { paint: fill } });\n }\n}\n\nfunction emitSnap(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const color = theme.snap;\n for (const c of s.snap) {\n const [cx, cy] = worldToScreen(c.point.x, c.point.y, t);\n const cmd: PathDrawCommand = {\n kind: 'path',\n path: approxCircleScreen(cx, cy, 4),\n ...(c.accepted\n ? { fill: { paint: { kind: 'solid' as const, color } } }\n : { stroke: strokeOf(strokes.snap, color) }),\n };\n out.push(cmd);\n }\n}\n\nfunction emitIds(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n): void {\n // Pulls from the bounds stream — every consumer that records bounds\n // (selection overlay's handle math, the kit's per-node debug shim) gets\n // an id label for free.\n for (const b of s.bounds) {\n const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);\n out.push(textCommandFromRuns(\n sx + 2,\n sy + 11,\n [{ text: b.id, fill: { paint: { kind: 'solid', color: theme.idText } } }],\n { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 10 },\n ));\n }\n}\n\nfunction emitLayersPanel(\n out: DrawCommand[],\n s: DebugSnapshot,\n dims: Dims,\n theme: DebugTheme,\n): void {\n if (s.layers.length === 0) return;\n const lineH = 14;\n const padX = 6;\n const padY = 4;\n const lines = s.layers.map((l) => `[${l.index}] ${l.id} (${l.space})`);\n // Approximate width: 11px font, monospaced — assume each glyph ≈6.6px.\n // 2D path uses ctx.measureText; we don't have a ctx here, so fall back\n // to a character-count estimate. Pixel-level accuracy is not load-bearing\n // for a debug panel; right-edge anchoring stays correct.\n const charW = 6.6;\n let maxW = 0;\n for (const line of lines) maxW = Math.max(maxW, line.length * charW);\n const boxW = maxW + padX * 2;\n const boxH = lines.length * lineH + padY * 2;\n const x = dims.width - boxW - 8;\n const y = 8;\n out.push({\n kind: 'path',\n path: rectPath(x, y, boxW, boxH),\n fill: { paint: { kind: 'solid', color: theme.layerTextBg } },\n });\n for (let i = 0; i < lines.length; i++) {\n out.push(textCommandFromRuns(\n x + padX,\n y + padY + i * lineH,\n [{ text: lines[i], fill: { paint: { kind: 'solid', color: theme.layerText } } }],\n { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 11 },\n ));\n }\n}\n\nconst MONO = { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 11 };\nconst MONO_CHAR_W = 6.6;\nconst LINE_H = 14;\n\n/** A dark box holding monospace lines, at `(x, y)`; `y < 0` anchors its bottom\n * that far above `bottom`. Width is estimated from the character count — there\n * is no text measurer here, and a debug panel does not need one. */\nfunction emitTextPanel(\n out: DrawCommand[],\n lines: readonly string[],\n x: number,\n y: number,\n color: string,\n bg: string,\n): void {\n const padX = 6;\n const padY = 4;\n let maxLen = 0;\n for (const l of lines) maxLen = Math.max(maxLen, l.length);\n out.push({\n kind: 'path',\n path: rectPath(x, y, maxLen * MONO_CHAR_W + padX * 2, lines.length * LINE_H + padY * 2),\n fill: { paint: { kind: 'solid', color: bg } },\n });\n for (let i = 0; i < lines.length; i++) {\n out.push(textCommandFromRuns(\n x + padX,\n y + padY + i * LINE_H,\n [{ text: lines[i], fill: { paint: { kind: 'solid', color } } }],\n MONO,\n ));\n }\n}\n\n/** Fixed-width number, right-aligned, `decimals` places: `%{width}.{decimals}f`. */\nfunction fixed(v: number, width: number, decimals: number): string {\n return v.toFixed(decimals).padStart(width);\n}\n\nfunction emitFramePanel(\n out: DrawCommand[],\n history: readonly number[],\n frame: FrameStats | null,\n theme: DebugTheme,\n): void {\n const span = history.length >= 2 ? history[history.length - 1] - history[0] : 0;\n const interval = span > 0 ? span / (history.length - 1) : null;\n // Columns: label, draw-call count, value, unit — every row the same width,\n // so decimals line up down the panel.\n const rows: [label: string, count: number | null, value: number | null, unit: string][] = [\n ['fps', null, interval ? 1000 / interval : null, ' '],\n ['frame', null, interval, 'ms'],\n ];\n if (frame) {\n rows.push(['paint', frame.drawCalls, frame.paintMs, 'ms']);\n for (const l of frame.layers) rows.push([l.id, l.drawCalls, l.ms, 'ms']);\n }\n let labelW = 0;\n for (const [label] of rows) labelW = Math.max(labelW, label.length);\n const line = (label: string, count: string, value: string, unit: string) =>\n `${label.padEnd(labelW)} ${count.padStart(5)} ${value.padStart(7)} ${unit}`;\n const lines = rows.map(([label, count, value, unit]) =>\n line(label, count === null ? '' : String(count), value === null ? '—' : fixed(value, 7, 2), unit));\n if (frame) lines.splice(2, 0, line('', 'draws', 'cpu', ' '));\n emitTextPanel(out, lines, 8, 8, theme.fpsText, theme.fpsTextBg);\n}\n\nfunction emitViewport(\n out: DrawCommand[],\n rec: RecordedViewport,\n view: View,\n dims: Dims,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const t = viewToTransform(view);\n const stroke = strokeOf(strokes.viewport, theme.viewport);\n // Where the viewport the gesture started from sits in the current camera.\n const { from, to } = rec;\n const [fx, fy] = worldToScreen(from.x, from.y, t);\n out.push({\n kind: 'path',\n path: rectPath(fx, fy, (dims.width / from.scale.x) * view.scale.x, (dims.height / from.scale.y) * view.scale.y),\n stroke,\n });\n if (rec.anchor) {\n const [ax0, ay0] = worldToScreen(rec.anchor.x, rec.anchor.y, viewToTransform(from));\n const [ax1, ay1] = worldToScreen(rec.anchor.x, rec.anchor.y, t);\n out.push({ kind: 'path', path: approxCircleScreen(ax0, ay0, 2.5), fill: { paint: { kind: 'solid', color: theme.viewport } } });\n if (Math.hypot(ax1 - ax0, ay1 - ay0) > 0.5) {\n out.push({ kind: 'path', path: segment(ax0, ay0, ax1, ay1), stroke });\n }\n out.push({ kind: 'path', path: approxCircleScreen(ax1, ay1, 6), stroke: strokeOf({ width: strokes.viewport.width }, theme.viewport) });\n }\n const text = rec.kind === 'pan'\n ? `pan Δ ${signed((from.x - to.x) * to.scale.x)} ${signed((from.y - to.y) * to.scale.y)} px`\n : `zoom ×${(to.scale.x / from.scale.x).toFixed(3)} ${from.scale.x.toFixed(3)} → ${to.scale.x.toFixed(3)}`;\n emitTextPanel(out, [text], 8, dims.height - LINE_H - 16, theme.viewport, theme.layerTextBg);\n}\n\nfunction signed(v: number): string {\n const r = Math.abs(v) < 0.05 ? 0 : v;\n return `${r >= 0 ? '+' : '-'}${Math.abs(r).toFixed(1)}`.padStart(8);\n}\n\nfunction segment(x0: number, y0: number, x1: number, y1: number): PolygonPath {\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([x0, y0, x1, y1]),\n fillRule: 'nonzero',\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createDebugOverlayLayer.js","names":["rectPath"],"sources":["../../src/debug/createDebugOverlayLayer.ts"],"sourcesContent":["import type { DrawCommand, PathDrawCommand } from '@weasel-js/renderer';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport type { View } from 'core/viewport/view';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\nimport { rotatePoint } from 'interactions/actions/rotate/geometry';\nimport { PATH_L, PATH_M, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport { textCommandFromRuns } from '@weasel-js/renderer';\nimport type {\n DebugConfig,\n DebugSnapshot,\n DebugStroke,\n DebugStrokes,\n DebugTheme,\n RecordedViewport,\n} from './types';\nimport { DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME } from './defaultTheme';\nimport { emitFramePanel, emitLayersPanel, emitTextPanel, LINE_H, rectPath } from './overlayPanels';\n\n/** What `createDebugOverlayLayer` paints from: a sink to snapshot and the features to draw. */\nexport interface CreateDebugOverlayLayerOpts {\n sink: { snapshot(): DebugSnapshot };\n config: DebugConfig;\n}\n\nexport const DEBUG_OVERLAY_ID = 'debug-overlay';\nconst FPS_WINDOW = 60;\n\n/**\n * Screen-space `RenderLayer` that paints the sink's snapshot. Appended at\n * the top of the Canvas's layer stack when `debug` is enabled. World-space\n * coords in the snapshot are projected through `view` here, since the\n * layer itself runs at identity transform.\n */\nexport function createDebugOverlayLayer({\n sink,\n config,\n}: CreateDebugOverlayLayerOpts): RenderLayer<unknown> {\n // Timestamps of the last FPS_WINDOW draws, kept for the life of the layer.\n const fpsHistory: number[] = [];\n return {\n id: DEBUG_OVERLAY_ID,\n label: 'Debug overlay',\n space: 'screen',\n alwaysOn: true,\n draw: (_data, view, dims) => {\n if (config.fps) {\n fpsHistory.push(typeof performance !== 'undefined' ? performance.now() : Date.now());\n if (fpsHistory.length > FPS_WINDOW) fpsHistory.shift();\n } else if (fpsHistory.length > 0) {\n fpsHistory.length = 0;\n }\n return buildDebugOverlayCommands(sink.snapshot(), config, view, dims, fpsHistory);\n },\n };\n}\n\n/**\n * The debug overlay's draw commands for one snapshot, in screen space (CSS\n * pixels of a `dims`-sized canvas looking through `view`). What the overlay\n * layer paints each frame, and what `renderDebugSnapshot` rasterizes.\n *\n * `frameTimes` are `performance.now()` stamps of recent paints, oldest first;\n * the frame panel derives its rate from them and shows none without two.\n */\nexport function buildDebugOverlayCommands(\n snapshot: DebugSnapshot,\n config: DebugConfig,\n view: View,\n dims: Dims,\n frameTimes: readonly number[] = [],\n): DrawCommand[] {\n const theme: DebugTheme = { ...DEFAULT_DEBUG_THEME, ...(config.theme ?? {}) };\n const strokes: DebugStrokes = { ...DEFAULT_DEBUG_STROKES, ...(config.strokes ?? {}) };\n const s = snapshot;\n const t = viewToTransform(view);\n const out: DrawCommand[] = [];\n\n if (config.viewport && s.viewport) emitViewport(out, s.viewport, view, dims, theme, strokes);\n if (config.hitboxes) emitHitboxes(out, s, view, t, theme, strokes);\n if (config.bounds) emitBounds(out, s, view, t, theme, strokes);\n if (config.highlight?.length) emitHighlight(out, s, new Set(config.highlight), view, t, theme, strokes);\n if (config.handles) emitHandles(out, s, t, theme, strokes);\n if (config.origins) emitOrigins(out, s, t, theme);\n if (config.snap) emitSnap(out, s, t, theme, strokes);\n if (config.ids) emitIds(out, s, t, theme);\n if (config.layers) emitLayersPanel(out, s, dims, theme);\n if (config.fps) emitFramePanel(out, frameTimes, s.frame, theme);\n return out;\n}\n\n// --- emitters (screen-space) ---\n\nfunction approxCircleScreen(cx: number, cy: number, r: number, segments = 24): PolygonPath {\n return approxEllipseScreen(cx, cy, r, r, segments);\n}\n\nfunction approxEllipseScreen(cx: number, cy: number, rx: number, ry: number, segments = 24): PolygonPath {\n // Commands: M + (segments-1) L + Z. Coords: (segments) × 2 — pairs for\n // the moveTo and the (segments-1) lineTos. PATH_Z consumes no coords.\n const cmds = new Uint8Array(segments + 1);\n const coords = new Float32Array(segments * 2);\n cmds[0] = PATH_M;\n coords[0] = cx + rx;\n coords[1] = cy;\n for (let i = 1; i < segments; i++) {\n cmds[i] = PATH_L;\n const theta = (i / segments) * Math.PI * 2;\n coords[i * 2] = cx + rx * Math.cos(theta);\n coords[i * 2 + 1] = cy + ry * Math.sin(theta);\n }\n cmds[segments] = PATH_Z;\n return { kind: 'polygon', commands: cmds, coords, fillRule: 'nonzero' };\n}\n\n/** A world rect turned `rotation` about its center, as the screen quad it\n * lands on. */\nfunction rotatedRectScreen(\n r: { x: number; y: number; width: number; height: number; rotation: number },\n t: ReturnType<typeof viewToTransform>,\n): PolygonPath {\n const cx = r.x + r.width / 2, cy = r.y + r.height / 2;\n const coords = new Float32Array(8);\n const corners = [[r.x, r.y], [r.x + r.width, r.y], [r.x + r.width, r.y + r.height], [r.x, r.y + r.height]];\n corners.forEach(([x, y], i) => {\n const w = rotatePoint(x, y, cx, cy, r.rotation);\n const [sx, sy] = worldToScreen(w.x, w.y, t);\n coords[i * 2] = sx;\n coords[i * 2 + 1] = sy;\n });\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),\n coords,\n fillRule: 'nonzero',\n };\n}\n\nfunction strokeOf(s: DebugStroke, color: string) {\n return {\n paint: { kind: 'solid' as const, color },\n width: s.width,\n ...(s.dash && s.dash.length > 0 ? { dash: [...s.dash] } : {}),\n };\n}\n\nfunction emitHitboxes(\n out: DrawCommand[],\n s: DebugSnapshot,\n view: View,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const fill = { kind: 'solid' as const, color: theme.hitboxFill };\n const stroke = strokeOf(strokes.hitbox, theme.hitboxStroke);\n for (const h of s.hitboxes) {\n if (h.shape.kind === 'rect' && h.shape.rotation) {\n const path = rotatedRectScreen({ ...h.shape, rotation: h.shape.rotation }, t);\n out.push({ kind: 'path', path, fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'rect') {\n const [sx, sy] = worldToScreen(h.shape.x, h.shape.y, t);\n const sw = h.shape.width * view.scale.x;\n const sh = h.shape.height * view.scale.y;\n out.push({ kind: 'path', path: rectPath(sx, sy, sw, sh), fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'circle') {\n const [cx, cy] = worldToScreen(h.shape.cx, h.shape.cy, t);\n const rx = h.shape.r * Math.abs(view.scale.x);\n const ry = h.shape.r * Math.abs(view.scale.y);\n out.push({ kind: 'path', path: approxEllipseScreen(cx, cy, rx, ry), fill: { paint: fill }, stroke });\n } else if (h.shape.kind === 'polygon' && h.shape.points.length > 2) {\n const pts = h.shape.points;\n const coords = new Float32Array(pts.length * 2);\n pts.forEach((p, i) => {\n const [sx, sy] = worldToScreen(p.x, p.y, t);\n coords[i * 2] = sx;\n coords[i * 2 + 1] = sy;\n });\n const commands = new Uint8Array(pts.length + 1).fill(PATH_L);\n commands[0] = PATH_M;\n commands[pts.length] = PATH_Z;\n out.push({ kind: 'path', path: { kind: 'polygon', commands, coords, fillRule: 'nonzero' }, fill: { paint: fill }, stroke });\n }\n // 'path' kind: v1 punt — matches 2D behavior.\n }\n}\n\nfunction emitBounds(\n out: DrawCommand[],\n s: DebugSnapshot,\n view: View,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const stroke = strokeOf(strokes.bounds, theme.bounds);\n for (const b of s.bounds) {\n const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);\n const sw = b.bounds.width * view.scale.x;\n const sh = b.bounds.height * view.scale.y;\n out.push({ kind: 'path', path: rectPath(sx, sy, sw, sh), stroke });\n }\n}\n\nfunction emitHighlight(\n out: DrawCommand[],\n s: DebugSnapshot,\n ids: ReadonlySet<string>,\n view: View,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const stroke = strokeOf(strokes.highlight, theme.highlight);\n for (const b of s.bounds) {\n if (!ids.has(b.id)) continue;\n const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);\n out.push({ kind: 'path', path: rectPath(sx, sy, b.bounds.width * view.scale.x, b.bounds.height * view.scale.y), stroke });\n }\n}\n\nfunction emitHandles(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const stroke = strokeOf(strokes.handle, theme.handle);\n for (const h of s.handles) {\n const [cx, cy] = worldToScreen(h.position.x, h.position.y, t);\n const horiz: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([cx - 4, cy, cx + 4, cy]),\n fillRule: 'nonzero',\n };\n const vert: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([cx, cy - 4, cx, cy + 4]),\n fillRule: 'nonzero',\n };\n out.push({ kind: 'path', path: horiz, stroke });\n out.push({ kind: 'path', path: vert, stroke });\n }\n}\n\nfunction emitOrigins(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n): void {\n const fill = { kind: 'solid' as const, color: theme.origin };\n for (const o of s.origins) {\n const [cx, cy] = worldToScreen(o.point.x, o.point.y, t);\n out.push({ kind: 'path', path: approxCircleScreen(cx, cy, 3), fill: { paint: fill } });\n }\n}\n\nfunction emitSnap(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const color = theme.snap;\n for (const c of s.snap) {\n const [cx, cy] = worldToScreen(c.point.x, c.point.y, t);\n const cmd: PathDrawCommand = {\n kind: 'path',\n path: approxCircleScreen(cx, cy, 4),\n ...(c.accepted\n ? { fill: { paint: { kind: 'solid' as const, color } } }\n : { stroke: strokeOf(strokes.snap, color) }),\n };\n out.push(cmd);\n }\n}\n\nfunction emitIds(\n out: DrawCommand[],\n s: DebugSnapshot,\n t: ReturnType<typeof viewToTransform>,\n theme: DebugTheme,\n): void {\n // Pulls from the bounds stream — every consumer that records bounds\n // (selection overlay's handle math, the kit's per-node debug shim) gets\n // an id label for free.\n for (const b of s.bounds) {\n const [sx, sy] = worldToScreen(b.bounds.x, b.bounds.y, t);\n out.push(textCommandFromRuns(\n sx + 2,\n sy + 11,\n [{ text: b.id, fill: { paint: { kind: 'solid', color: theme.idText } } }],\n { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 10 },\n ));\n }\n}\n\nfunction emitViewport(\n out: DrawCommand[],\n rec: RecordedViewport,\n view: View,\n dims: Dims,\n theme: DebugTheme,\n strokes: DebugStrokes,\n): void {\n const t = viewToTransform(view);\n const stroke = strokeOf(strokes.viewport, theme.viewport);\n // Where the viewport the gesture started from sits in the current camera.\n const { from, to } = rec;\n const [fx, fy] = worldToScreen(from.x, from.y, t);\n out.push({\n kind: 'path',\n path: rectPath(fx, fy, (dims.width / from.scale.x) * view.scale.x, (dims.height / from.scale.y) * view.scale.y),\n stroke,\n });\n if (rec.anchor) {\n const [ax0, ay0] = worldToScreen(rec.anchor.x, rec.anchor.y, viewToTransform(from));\n const [ax1, ay1] = worldToScreen(rec.anchor.x, rec.anchor.y, t);\n out.push({ kind: 'path', path: approxCircleScreen(ax0, ay0, 2.5), fill: { paint: { kind: 'solid', color: theme.viewport } } });\n if (Math.hypot(ax1 - ax0, ay1 - ay0) > 0.5) {\n out.push({ kind: 'path', path: segment(ax0, ay0, ax1, ay1), stroke });\n }\n out.push({ kind: 'path', path: approxCircleScreen(ax1, ay1, 6), stroke: strokeOf({ width: strokes.viewport.width }, theme.viewport) });\n }\n const text = rec.kind === 'pan'\n ? `pan Δ ${signed((from.x - to.x) * to.scale.x)} ${signed((from.y - to.y) * to.scale.y)} px`\n : `zoom ×${(to.scale.x / from.scale.x).toFixed(3)} ${from.scale.x.toFixed(3)} → ${to.scale.x.toFixed(3)}`;\n emitTextPanel(out, [text], 8, dims.height - LINE_H - 16, theme.viewport, theme.layerTextBg);\n}\n\nfunction signed(v: number): string {\n const r = Math.abs(v) < 0.05 ? 0 : v;\n return `${r >= 0 ? '+' : '-'}${Math.abs(r).toFixed(1)}`.padStart(8);\n}\n\nfunction segment(x0: number, y0: number, x1: number, y1: number): PolygonPath {\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L]),\n coords: new Float32Array([x0, y0, x1, y1]),\n fillRule: 'nonzero',\n };\n}\n"],"mappings":"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"}
@@ -19,6 +19,7 @@ function createDebugSink(config) {
19
19
  viewport: null,
20
20
  frame: null
21
21
  };
22
+ const highlighted = new Set(config.highlight ?? []);
22
23
  return {
23
24
  recordHitbox(id, kind, shape) {
24
25
  if (!config.hitboxes) return;
@@ -37,7 +38,7 @@ function createDebugSink(config) {
37
38
  });
38
39
  },
39
40
  recordBounds(id, bounds) {
40
- if (!config.bounds) return;
41
+ if (!config.bounds && !highlighted.has(id)) return;
41
42
  snap.bounds.push({
42
43
  id,
43
44
  bounds
@@ -1 +1 @@
1
- {"version":3,"file":"createDebugSink.js","names":[],"sources":["../../src/debug/createDebugSink.ts"],"sourcesContent":["import type {\n CanvasDebugSink,\n DebugConfig,\n DebugSnapshot,\n HandleKind,\n HitShape,\n} from './types';\n\n/**\n * Build a sink that stores recorded primitives in arrays keyed by feature.\n * A `recordX` call no-ops when its flag in `config` is off, so callers can\n * record unconditionally.\n *\n * `beginFrame()` clears every per-frame array. Snap, the latest viewport\n * record, and the last frame's stats survive across frames. `snapshot()`\n * returns live references — no copy.\n */\nexport function createDebugSink(config: DebugConfig): CanvasDebugSink {\n const snap: DebugSnapshot = {\n hitboxes: [],\n handles: [],\n bounds: [],\n origins: [],\n snap: [],\n layers: [],\n viewport: null,\n frame: null,\n };\n return {\n recordHitbox(id, kind, shape: HitShape) {\n if (!config.hitboxes) return;\n snap.hitboxes.push({ id, kind, shape });\n },\n recordHandle(id, position, kind: HandleKind) {\n if (!config.handles) return;\n snap.handles.push({ id, position, kind });\n },\n recordBounds(id, bounds) {\n if (!config.bounds) return;\n snap.bounds.push({ id, bounds });\n },\n recordOrigin(id, point) {\n if (!config.origins) return;\n snap.origins.push({ id, point });\n },\n recordSnapCandidate(point, accepted) {\n if (!config.snap) return;\n snap.snap.push({ point, accepted });\n },\n recordLayer(id, label, space, index) {\n if (!config.layers) return;\n snap.layers.push({ id, label, space, index });\n },\n recordViewport(kind, from, to, anchor) {\n if (!config.viewport) return;\n snap.viewport = anchor ? { kind, from, to, anchor } : { kind, from, to };\n },\n recordFrame(stats) {\n if (!config.fps) return;\n snap.frame = stats;\n },\n beginFrame() {\n snap.hitboxes.length = 0;\n snap.handles.length = 0;\n snap.bounds.length = 0;\n snap.origins.length = 0;\n snap.layers.length = 0;\n },\n clearSnap() {\n snap.snap.length = 0;\n },\n snapshot() {\n return snap;\n },\n };\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,gBAAgB,QAAsC;CACpE,MAAM,OAAsB;EAC1B,UAAU,CAAC;EACX,SAAS,CAAC;EACV,QAAQ,CAAC;EACT,SAAS,CAAC;EACV,MAAM,CAAC;EACP,QAAQ,CAAC;EACT,UAAU;EACV,OAAO;CACT;CACA,OAAO;EACL,aAAa,IAAI,MAAM,OAAiB;GACtC,IAAI,CAAC,OAAO,UAAU;GACtB,KAAK,SAAS,KAAK;IAAE;IAAI;IAAM;GAAM,CAAC;EACxC;EACA,aAAa,IAAI,UAAU,MAAkB;GAC3C,IAAI,CAAC,OAAO,SAAS;GACrB,KAAK,QAAQ,KAAK;IAAE;IAAI;IAAU;GAAK,CAAC;EAC1C;EACA,aAAa,IAAI,QAAQ;GACvB,IAAI,CAAC,OAAO,QAAQ;GACpB,KAAK,OAAO,KAAK;IAAE;IAAI;GAAO,CAAC;EACjC;EACA,aAAa,IAAI,OAAO;GACtB,IAAI,CAAC,OAAO,SAAS;GACrB,KAAK,QAAQ,KAAK;IAAE;IAAI;GAAM,CAAC;EACjC;EACA,oBAAoB,OAAO,UAAU;GACnC,IAAI,CAAC,OAAO,MAAM;GAClB,KAAK,KAAK,KAAK;IAAE;IAAO;GAAS,CAAC;EACpC;EACA,YAAY,IAAI,OAAO,OAAO,OAAO;GACnC,IAAI,CAAC,OAAO,QAAQ;GACpB,KAAK,OAAO,KAAK;IAAE;IAAI;IAAO;IAAO;GAAM,CAAC;EAC9C;EACA,eAAe,MAAM,MAAM,IAAI,QAAQ;GACrC,IAAI,CAAC,OAAO,UAAU;GACtB,KAAK,WAAW,SAAS;IAAE;IAAM;IAAM;IAAI;GAAO,IAAI;IAAE;IAAM;IAAM;GAAG;EACzE;EACA,YAAY,OAAO;GACjB,IAAI,CAAC,OAAO,KAAK;GACjB,KAAK,QAAQ;EACf;EACA,aAAa;GACX,KAAK,SAAS,SAAS;GACvB,KAAK,QAAQ,SAAS;GACtB,KAAK,OAAO,SAAS;GACrB,KAAK,QAAQ,SAAS;GACtB,KAAK,OAAO,SAAS;EACvB;EACA,YAAY;GACV,KAAK,KAAK,SAAS;EACrB;EACA,WAAW;GACT,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"createDebugSink.js","names":[],"sources":["../../src/debug/createDebugSink.ts"],"sourcesContent":["import type {\n CanvasDebugSink,\n DebugConfig,\n DebugSnapshot,\n HandleKind,\n HitShape,\n} from './types';\n\n/**\n * Build a sink that stores recorded primitives in arrays keyed by feature.\n * A `recordX` call no-ops when its flag in `config` is off, so callers can\n * record unconditionally.\n *\n * `beginFrame()` clears every per-frame array. Snap, the latest viewport\n * record, and the last frame's stats survive across frames. `snapshot()`\n * returns live references — no copy.\n */\nexport function createDebugSink(config: DebugConfig): CanvasDebugSink {\n const snap: DebugSnapshot = {\n hitboxes: [],\n handles: [],\n bounds: [],\n origins: [],\n snap: [],\n layers: [],\n viewport: null,\n frame: null,\n };\n const highlighted = new Set(config.highlight ?? []);\n return {\n recordHitbox(id, kind, shape: HitShape) {\n if (!config.hitboxes) return;\n snap.hitboxes.push({ id, kind, shape });\n },\n recordHandle(id, position, kind: HandleKind) {\n if (!config.handles) return;\n snap.handles.push({ id, position, kind });\n },\n recordBounds(id, bounds) {\n if (!config.bounds && !highlighted.has(id)) return;\n snap.bounds.push({ id, bounds });\n },\n recordOrigin(id, point) {\n if (!config.origins) return;\n snap.origins.push({ id, point });\n },\n recordSnapCandidate(point, accepted) {\n if (!config.snap) return;\n snap.snap.push({ point, accepted });\n },\n recordLayer(id, label, space, index) {\n if (!config.layers) return;\n snap.layers.push({ id, label, space, index });\n },\n recordViewport(kind, from, to, anchor) {\n if (!config.viewport) return;\n snap.viewport = anchor ? { kind, from, to, anchor } : { kind, from, to };\n },\n recordFrame(stats) {\n if (!config.fps) return;\n snap.frame = stats;\n },\n beginFrame() {\n snap.hitboxes.length = 0;\n snap.handles.length = 0;\n snap.bounds.length = 0;\n snap.origins.length = 0;\n snap.layers.length = 0;\n },\n clearSnap() {\n snap.snap.length = 0;\n },\n snapshot() {\n return snap;\n },\n };\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,gBAAgB,QAAsC;CACpE,MAAM,OAAsB;EAC1B,UAAU,CAAC;EACX,SAAS,CAAC;EACV,QAAQ,CAAC;EACT,SAAS,CAAC;EACV,MAAM,CAAC;EACP,QAAQ,CAAC;EACT,UAAU;EACV,OAAO;CACT;CACA,MAAM,cAAc,IAAI,IAAI,OAAO,aAAa,CAAC,CAAC;CAClD,OAAO;EACL,aAAa,IAAI,MAAM,OAAiB;GACtC,IAAI,CAAC,OAAO,UAAU;GACtB,KAAK,SAAS,KAAK;IAAE;IAAI;IAAM;GAAM,CAAC;EACxC;EACA,aAAa,IAAI,UAAU,MAAkB;GAC3C,IAAI,CAAC,OAAO,SAAS;GACrB,KAAK,QAAQ,KAAK;IAAE;IAAI;IAAU;GAAK,CAAC;EAC1C;EACA,aAAa,IAAI,QAAQ;GACvB,IAAI,CAAC,OAAO,UAAU,CAAC,YAAY,IAAI,EAAE,GAAG;GAC5C,KAAK,OAAO,KAAK;IAAE;IAAI;GAAO,CAAC;EACjC;EACA,aAAa,IAAI,OAAO;GACtB,IAAI,CAAC,OAAO,SAAS;GACrB,KAAK,QAAQ,KAAK;IAAE;IAAI;GAAM,CAAC;EACjC;EACA,oBAAoB,OAAO,UAAU;GACnC,IAAI,CAAC,OAAO,MAAM;GAClB,KAAK,KAAK,KAAK;IAAE;IAAO;GAAS,CAAC;EACpC;EACA,YAAY,IAAI,OAAO,OAAO,OAAO;GACnC,IAAI,CAAC,OAAO,QAAQ;GACpB,KAAK,OAAO,KAAK;IAAE;IAAI;IAAO;IAAO;GAAM,CAAC;EAC9C;EACA,eAAe,MAAM,MAAM,IAAI,QAAQ;GACrC,IAAI,CAAC,OAAO,UAAU;GACtB,KAAK,WAAW,SAAS;IAAE;IAAM;IAAM;IAAI;GAAO,IAAI;IAAE;IAAM;IAAM;GAAG;EACzE;EACA,YAAY,OAAO;GACjB,IAAI,CAAC,OAAO,KAAK;GACjB,KAAK,QAAQ;EACf;EACA,aAAa;GACX,KAAK,SAAS,SAAS;GACvB,KAAK,QAAQ,SAAS;GACtB,KAAK,OAAO,SAAS;GACrB,KAAK,QAAQ,SAAS;GACtB,KAAK,OAAO,SAAS;EACvB;EACA,YAAY;GACV,KAAK,KAAK,SAAS;EACrB;EACA,WAAW;GACT,OAAO;EACT;CACF;AACF"}
@@ -16,7 +16,8 @@ var DEFAULT_DEBUG_THEME = {
16
16
  idText: "#ffeb3b",
17
17
  fpsText: "#e0e0e0",
18
18
  fpsTextBg: "rgba(0, 0, 0, 0.6)",
19
- viewport: "#b388ff"
19
+ viewport: "#b388ff",
20
+ highlight: "#ff4081"
20
21
  };
21
22
  /**
22
23
  * Default line widths and dashes. Hairline everywhere so the overlay never
@@ -35,7 +36,8 @@ var DEFAULT_DEBUG_STROKES = {
35
36
  viewport: {
36
37
  width: 1,
37
38
  dash: [6, 4]
38
- }
39
+ },
40
+ highlight: { width: 2 }
39
41
  };
40
42
 
41
43
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"defaultTheme.js","names":[],"sources":["../../src/debug/defaultTheme.ts"],"sourcesContent":["import type { DebugStrokes, DebugTheme } from './types';\n\n/**\n * Default colors per the spec's Visual Style section. High contrast against\n * the demo's dark backdrop. Override by passing `theme: { ... }` on\n * `DebugConfig`.\n */\nexport const DEFAULT_DEBUG_THEME: DebugTheme = {\n hitboxFill: 'rgba(255, 0, 255, 0.25)',\n hitboxStroke: '#ff00ff',\n handle: '#00e5ff',\n bounds: '#ffeb3b',\n origin: '#69f0ae',\n snap: '#ffa726',\n layerText: '#e0e0e0',\n layerTextBg: 'rgba(0, 0, 0, 0.6)',\n idText: '#ffeb3b',\n fpsText: '#e0e0e0',\n fpsTextBg: 'rgba(0, 0, 0, 0.6)',\n viewport: '#b388ff',\n};\n\n/**\n * Default line widths and dashes. Hairline everywhere so the overlay never\n * hides the geometry it is describing; the dash on hitboxes is what\n * distinguishes them from the solid bounds box at the same rect.\n * Override by passing `strokes: { ... }` on `DebugConfig`.\n */\nexport const DEFAULT_DEBUG_STROKES: DebugStrokes = {\n hitbox: { width: 1, dash: [2, 2] },\n bounds: { width: 1 },\n handle: { width: 1 },\n snap: { width: 1 },\n viewport: { width: 1, dash: [6, 4] },\n};\n"],"mappings":";;;;;;AAOA,IAAa,sBAAkC;CAC7C,YAAY;CACZ,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,MAAM;CACN,WAAW;CACX,aAAa;CACb,QAAQ;CACR,SAAS;CACT,WAAW;CACX,UAAU;AACZ;;;;;;;AAQA,IAAa,wBAAsC;CACjD,QAAQ;EAAE,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;CACjC,QAAQ,EAAE,OAAO,EAAE;CACnB,QAAQ,EAAE,OAAO,EAAE;CACnB,MAAM,EAAE,OAAO,EAAE;CACjB,UAAU;EAAE,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;AACrC"}
1
+ {"version":3,"file":"defaultTheme.js","names":[],"sources":["../../src/debug/defaultTheme.ts"],"sourcesContent":["import type { DebugStrokes, DebugTheme } from './types';\n\n/**\n * Default colors per the spec's Visual Style section. High contrast against\n * the demo's dark backdrop. Override by passing `theme: { ... }` on\n * `DebugConfig`.\n */\nexport const DEFAULT_DEBUG_THEME: DebugTheme = {\n hitboxFill: 'rgba(255, 0, 255, 0.25)',\n hitboxStroke: '#ff00ff',\n handle: '#00e5ff',\n bounds: '#ffeb3b',\n origin: '#69f0ae',\n snap: '#ffa726',\n layerText: '#e0e0e0',\n layerTextBg: 'rgba(0, 0, 0, 0.6)',\n idText: '#ffeb3b',\n fpsText: '#e0e0e0',\n fpsTextBg: 'rgba(0, 0, 0, 0.6)',\n viewport: '#b388ff',\n highlight: '#ff4081',\n};\n\n/**\n * Default line widths and dashes. Hairline everywhere so the overlay never\n * hides the geometry it is describing; the dash on hitboxes is what\n * distinguishes them from the solid bounds box at the same rect.\n * Override by passing `strokes: { ... }` on `DebugConfig`.\n */\nexport const DEFAULT_DEBUG_STROKES: DebugStrokes = {\n hitbox: { width: 1, dash: [2, 2] },\n bounds: { width: 1 },\n handle: { width: 1 },\n snap: { width: 1 },\n viewport: { width: 1, dash: [6, 4] },\n highlight: { width: 2 },\n};\n"],"mappings":";;;;;;AAOA,IAAa,sBAAkC;CAC7C,YAAY;CACZ,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,MAAM;CACN,WAAW;CACX,aAAa;CACb,QAAQ;CACR,SAAS;CACT,WAAW;CACX,UAAU;CACV,WAAW;AACb;;;;;;;AAQA,IAAa,wBAAsC;CACjD,QAAQ;EAAE,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;CACjC,QAAQ,EAAE,OAAO,EAAE;CACnB,QAAQ,EAAE,OAAO,EAAE;CACnB,MAAM,EAAE,OAAO,EAAE;CACjB,UAAU;EAAE,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;CACnC,WAAW,EAAE,OAAO,EAAE;AACxB"}
@@ -0,0 +1,17 @@
1
+ //#region src/debug/features.ts
2
+ /** Every debug-overlay feature a `DebugConfig` flag turns on, in the order a list of them shows. */
3
+ var DEBUG_FEATURES = [
4
+ "hitboxes",
5
+ "handles",
6
+ "bounds",
7
+ "origins",
8
+ "snap",
9
+ "layers",
10
+ "ids",
11
+ "fps",
12
+ "viewport"
13
+ ];
14
+
15
+ //#endregion
16
+ export { DEBUG_FEATURES };
17
+ //# sourceMappingURL=features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","names":[],"sources":["../../src/debug/features.ts"],"sourcesContent":["/** Every debug-overlay feature a `DebugConfig` flag turns on, in the order a list of them shows. */\nexport const DEBUG_FEATURES = [\n 'hitboxes', 'handles', 'bounds', 'origins', 'snap', 'layers', 'ids', 'fps', 'viewport',\n] as const;\n"],"mappings":";;AACA,IAAa,iBAAiB;CAC5B;CAAY;CAAW;CAAU;CAAW;CAAQ;CAAU;CAAO;CAAO;AAC9E"}
@@ -0,0 +1,117 @@
1
+ import { textCommandFromRuns } from "@weasel-js/renderer";
2
+
3
+ //#region src/debug/overlayPanels.ts
4
+ function rectPath(x, y, w, h) {
5
+ return {
6
+ kind: "rect",
7
+ x,
8
+ y,
9
+ width: w,
10
+ height: h
11
+ };
12
+ }
13
+ /** A `DebugStroke` + color as the renderer's stroke shape. `dash` is dropped
14
+ * when empty rather than passed through, so a solid line stays solid. */
15
+ function emitLayersPanel(out, s, dims, theme) {
16
+ if (s.layers.length === 0) return;
17
+ const lineH = 14;
18
+ const padX = 6;
19
+ const lines = s.layers.map((l) => `[${l.index}] ${l.id} (${l.space})`);
20
+ const charW = 6.6;
21
+ let maxW = 0;
22
+ for (const line of lines) maxW = Math.max(maxW, line.length * charW);
23
+ const boxW = maxW + 12;
24
+ const boxH = lines.length * lineH + 8;
25
+ const x = dims.width - boxW - 8;
26
+ out.push({
27
+ kind: "path",
28
+ path: rectPath(x, 8, boxW, boxH),
29
+ fill: { paint: {
30
+ kind: "solid",
31
+ color: theme.layerTextBg
32
+ } }
33
+ });
34
+ for (let i = 0; i < lines.length; i++) out.push(textCommandFromRuns(x + padX, 12 + i * lineH, [{
35
+ text: lines[i],
36
+ fill: { paint: {
37
+ kind: "solid",
38
+ color: theme.layerText
39
+ } }
40
+ }], {
41
+ fontFamily: "ui-monospace, Menlo, monospace",
42
+ fontSize: 11
43
+ }));
44
+ }
45
+ var MONO = {
46
+ fontFamily: "ui-monospace, Menlo, monospace",
47
+ fontSize: 11
48
+ };
49
+ var MONO_CHAR_W = 6.6;
50
+ var LINE_H = 14;
51
+ /** A dark box holding monospace lines, at `(x, y)`; `y < 0` anchors its bottom
52
+ * that far above `bottom`. Width is estimated from the character count — there
53
+ * is no text measurer here, and a debug panel does not need one. */
54
+ function emitTextPanel(out, lines, x, y, color, bg) {
55
+ const padX = 6;
56
+ const padY = 4;
57
+ let maxLen = 0;
58
+ for (const l of lines) maxLen = Math.max(maxLen, l.length);
59
+ out.push({
60
+ kind: "path",
61
+ path: rectPath(x, y, maxLen * MONO_CHAR_W + 12, lines.length * LINE_H + 8),
62
+ fill: { paint: {
63
+ kind: "solid",
64
+ color: bg
65
+ } }
66
+ });
67
+ for (let i = 0; i < lines.length; i++) out.push(textCommandFromRuns(x + padX, y + padY + i * LINE_H, [{
68
+ text: lines[i],
69
+ fill: { paint: {
70
+ kind: "solid",
71
+ color
72
+ } }
73
+ }], MONO));
74
+ }
75
+ /** Fixed-width number, right-aligned, `decimals` places: `%{width}.{decimals}f`. */
76
+ function fixed(v, width, decimals) {
77
+ return v.toFixed(decimals).padStart(width);
78
+ }
79
+ function emitFramePanel(out, history, frame, theme) {
80
+ const span = history.length >= 2 ? history[history.length - 1] - history[0] : 0;
81
+ const interval = span > 0 ? span / (history.length - 1) : null;
82
+ const rows = [[
83
+ "fps",
84
+ null,
85
+ interval ? 1e3 / interval : null,
86
+ " "
87
+ ], [
88
+ "frame",
89
+ null,
90
+ interval,
91
+ "ms"
92
+ ]];
93
+ if (frame) {
94
+ rows.push([
95
+ "paint",
96
+ frame.drawCalls,
97
+ frame.paintMs,
98
+ "ms"
99
+ ]);
100
+ for (const l of frame.layers) rows.push([
101
+ l.id,
102
+ l.drawCalls,
103
+ l.ms,
104
+ "ms"
105
+ ]);
106
+ }
107
+ let labelW = 0;
108
+ for (const [label] of rows) labelW = Math.max(labelW, label.length);
109
+ const line = (label, count, value, unit) => `${label.padEnd(labelW)} ${count.padStart(5)} ${value.padStart(7)} ${unit}`;
110
+ const lines = rows.map(([label, count, value, unit]) => line(label, count === null ? "" : String(count), value === null ? "—" : fixed(value, 7, 2), unit));
111
+ if (frame) lines.splice(2, 0, line("", "draws", "cpu", " "));
112
+ emitTextPanel(out, lines, 8, 8, theme.fpsText, theme.fpsTextBg);
113
+ }
114
+
115
+ //#endregion
116
+ export { LINE_H, emitFramePanel, emitLayersPanel, emitTextPanel, rectPath };
117
+ //# sourceMappingURL=overlayPanels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlayPanels.js","names":[],"sources":["../../src/debug/overlayPanels.ts"],"sourcesContent":["/** The debug overlay's text panels — the layer list and the frame stats — and the rect path every box is drawn with. */\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport { textCommandFromRuns } from '@weasel-js/renderer';\nimport type { Dims } from 'core/layers/render';\nimport type { DebugSnapshot, DebugTheme, FrameStats } from './types';\n\nexport function rectPath(x: number, y: number, w: number, h: number): { kind: 'rect'; x: number; y: number; width: number; height: number } {\n return { kind: 'rect', x, y, width: w, height: h };\n}\n\n/** A `DebugStroke` + color as the renderer's stroke shape. `dash` is dropped\n * when empty rather than passed through, so a solid line stays solid. */\nexport function emitLayersPanel(\n out: DrawCommand[],\n s: DebugSnapshot,\n dims: Dims,\n theme: DebugTheme,\n): void {\n if (s.layers.length === 0) return;\n const lineH = 14;\n const padX = 6;\n const padY = 4;\n const lines = s.layers.map((l) => `[${l.index}] ${l.id} (${l.space})`);\n // Approximate width: 11px font, monospaced — assume each glyph ≈6.6px.\n // 2D path uses ctx.measureText; we don't have a ctx here, so fall back\n // to a character-count estimate. Pixel-level accuracy is not load-bearing\n // for a debug panel; right-edge anchoring stays correct.\n const charW = 6.6;\n let maxW = 0;\n for (const line of lines) maxW = Math.max(maxW, line.length * charW);\n const boxW = maxW + padX * 2;\n const boxH = lines.length * lineH + padY * 2;\n const x = dims.width - boxW - 8;\n const y = 8;\n out.push({\n kind: 'path',\n path: rectPath(x, y, boxW, boxH),\n fill: { paint: { kind: 'solid', color: theme.layerTextBg } },\n });\n for (let i = 0; i < lines.length; i++) {\n out.push(textCommandFromRuns(\n x + padX,\n y + padY + i * lineH,\n [{ text: lines[i], fill: { paint: { kind: 'solid', color: theme.layerText } } }],\n { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 11 },\n ));\n }\n}\n\nconst MONO = { fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 11 };\nconst MONO_CHAR_W = 6.6;\nexport const LINE_H = 14;\n\n/** A dark box holding monospace lines, at `(x, y)`; `y < 0` anchors its bottom\n * that far above `bottom`. Width is estimated from the character count — there\n * is no text measurer here, and a debug panel does not need one. */\nexport function emitTextPanel(\n out: DrawCommand[],\n lines: readonly string[],\n x: number,\n y: number,\n color: string,\n bg: string,\n): void {\n const padX = 6;\n const padY = 4;\n let maxLen = 0;\n for (const l of lines) maxLen = Math.max(maxLen, l.length);\n out.push({\n kind: 'path',\n path: rectPath(x, y, maxLen * MONO_CHAR_W + padX * 2, lines.length * LINE_H + padY * 2),\n fill: { paint: { kind: 'solid', color: bg } },\n });\n for (let i = 0; i < lines.length; i++) {\n out.push(textCommandFromRuns(\n x + padX,\n y + padY + i * LINE_H,\n [{ text: lines[i], fill: { paint: { kind: 'solid', color } } }],\n MONO,\n ));\n }\n}\n\n/** Fixed-width number, right-aligned, `decimals` places: `%{width}.{decimals}f`. */\nfunction fixed(v: number, width: number, decimals: number): string {\n return v.toFixed(decimals).padStart(width);\n}\n\nexport function emitFramePanel(\n out: DrawCommand[],\n history: readonly number[],\n frame: FrameStats | null,\n theme: DebugTheme,\n): void {\n const span = history.length >= 2 ? history[history.length - 1] - history[0] : 0;\n const interval = span > 0 ? span / (history.length - 1) : null;\n // Columns: label, draw-call count, value, unit — every row the same width,\n // so decimals line up down the panel.\n const rows: [label: string, count: number | null, value: number | null, unit: string][] = [\n ['fps', null, interval ? 1000 / interval : null, ' '],\n ['frame', null, interval, 'ms'],\n ];\n if (frame) {\n rows.push(['paint', frame.drawCalls, frame.paintMs, 'ms']);\n for (const l of frame.layers) rows.push([l.id, l.drawCalls, l.ms, 'ms']);\n }\n let labelW = 0;\n for (const [label] of rows) labelW = Math.max(labelW, label.length);\n const line = (label: string, count: string, value: string, unit: string) =>\n `${label.padEnd(labelW)} ${count.padStart(5)} ${value.padStart(7)} ${unit}`;\n const lines = rows.map(([label, count, value, unit]) =>\n line(label, count === null ? '' : String(count), value === null ? '—' : fixed(value, 7, 2), unit));\n if (frame) lines.splice(2, 0, line('', 'draws', 'cpu', ' '));\n emitTextPanel(out, lines, 8, 8, theme.fpsText, theme.fpsTextBg);\n}\n"],"mappings":"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"}