fluidcad 0.0.33 → 0.0.35

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 (363) hide show
  1. package/README.md +72 -2
  2. package/bin/commands/init.js +55 -0
  3. package/bin/commands/login.js +120 -0
  4. package/bin/commands/mcp.js +33 -0
  5. package/bin/commands/pack.js +49 -0
  6. package/bin/commands/publish.js +136 -0
  7. package/bin/commands/serve.js +77 -0
  8. package/bin/fluidcad.js +21 -107
  9. package/bin/lib/api-client.js +40 -0
  10. package/bin/lib/browser.js +16 -0
  11. package/bin/lib/config.js +39 -0
  12. package/bin/lib/model-config.js +38 -0
  13. package/bin/lib/workspace.js +57 -0
  14. package/lib/dist/common/scene-object.d.ts +2 -1
  15. package/lib/dist/common/scene-object.js +3 -2
  16. package/lib/dist/common/shape-factory.d.ts +2 -1
  17. package/lib/dist/common/shape-factory.js +4 -0
  18. package/lib/dist/common/transformable-primitive.d.ts +6 -5
  19. package/lib/dist/common/transformable-primitive.js +8 -7
  20. package/lib/dist/common/vertex.js +0 -1
  21. package/lib/dist/core/2d/aline.d.ts +4 -3
  22. package/lib/dist/core/2d/aline.js +3 -2
  23. package/lib/dist/core/2d/arc.d.ts +3 -2
  24. package/lib/dist/core/2d/arc.js +4 -3
  25. package/lib/dist/core/2d/bezier.d.ts +8 -6
  26. package/lib/dist/core/2d/circle.d.ts +4 -3
  27. package/lib/dist/core/2d/circle.js +3 -2
  28. package/lib/dist/core/2d/ellipse.d.ts +5 -4
  29. package/lib/dist/core/2d/ellipse.js +5 -4
  30. package/lib/dist/core/2d/hline.d.ts +4 -3
  31. package/lib/dist/core/2d/hline.js +5 -3
  32. package/lib/dist/core/2d/line.js +1 -0
  33. package/lib/dist/core/2d/offset.d.ts +3 -2
  34. package/lib/dist/core/2d/offset.js +6 -5
  35. package/lib/dist/core/2d/polygon.d.ts +5 -4
  36. package/lib/dist/core/2d/polygon.js +10 -9
  37. package/lib/dist/core/2d/rect.d.ts +4 -3
  38. package/lib/dist/core/2d/rect.js +10 -9
  39. package/lib/dist/core/2d/slot.d.ts +14 -6
  40. package/lib/dist/core/2d/slot.js +19 -8
  41. package/lib/dist/core/2d/tarc.d.ts +20 -2
  42. package/lib/dist/core/2d/tarc.js +24 -0
  43. package/lib/dist/core/2d/vline.d.ts +4 -3
  44. package/lib/dist/core/2d/vline.js +5 -3
  45. package/lib/dist/core/chamfer.d.ts +5 -4
  46. package/lib/dist/core/chamfer.js +7 -6
  47. package/lib/dist/core/color.d.ts +3 -2
  48. package/lib/dist/core/color.js +2 -1
  49. package/lib/dist/core/cut.d.ts +4 -3
  50. package/lib/dist/core/cut.js +5 -4
  51. package/lib/dist/core/cylinder.d.ts +2 -1
  52. package/lib/dist/core/cylinder.js +2 -1
  53. package/lib/dist/core/draft.d.ts +3 -2
  54. package/lib/dist/core/draft.js +3 -2
  55. package/lib/dist/core/extrude.d.ts +4 -3
  56. package/lib/dist/core/extrude.js +5 -4
  57. package/lib/dist/core/fillet.d.ts +5 -4
  58. package/lib/dist/core/fillet.js +6 -5
  59. package/lib/dist/core/index.d.ts +1 -0
  60. package/lib/dist/core/index.js +1 -0
  61. package/lib/dist/core/interfaces.d.ts +55 -25
  62. package/lib/dist/core/param.d.ts +74 -0
  63. package/lib/dist/core/param.js +147 -0
  64. package/lib/dist/core/repeat.d.ts +2 -1
  65. package/lib/dist/core/repeat.js +72 -54
  66. package/lib/dist/core/revolve.d.ts +2 -1
  67. package/lib/dist/core/revolve.js +3 -2
  68. package/lib/dist/core/rib.d.ts +3 -2
  69. package/lib/dist/core/rib.js +6 -2
  70. package/lib/dist/core/rotate.d.ts +5 -4
  71. package/lib/dist/core/rotate.js +4 -3
  72. package/lib/dist/core/shell.d.ts +3 -2
  73. package/lib/dist/core/shell.js +3 -2
  74. package/lib/dist/core/sphere.d.ts +3 -2
  75. package/lib/dist/core/sphere.js +2 -1
  76. package/lib/dist/core/translate.d.ts +7 -6
  77. package/lib/dist/core/translate.js +6 -5
  78. package/lib/dist/features/2d/arc.d.ts +8 -2
  79. package/lib/dist/features/2d/arc.js +94 -17
  80. package/lib/dist/features/2d/back.js +3 -2
  81. package/lib/dist/features/2d/bezier.js +16 -16
  82. package/lib/dist/features/2d/circle.js +4 -0
  83. package/lib/dist/features/2d/ellipse.js +4 -0
  84. package/lib/dist/features/2d/hline.d.ts +3 -0
  85. package/lib/dist/features/2d/hline.js +9 -2
  86. package/lib/dist/features/2d/line.d.ts +3 -0
  87. package/lib/dist/features/2d/line.js +11 -3
  88. package/lib/dist/features/2d/sketch.d.ts +4 -0
  89. package/lib/dist/features/2d/sketch.js +25 -0
  90. package/lib/dist/features/2d/slot.d.ts +5 -0
  91. package/lib/dist/features/2d/slot.js +52 -7
  92. package/lib/dist/features/2d/tarc-constrained.d.ts +2 -0
  93. package/lib/dist/features/2d/tarc-constrained.js +8 -0
  94. package/lib/dist/features/2d/tarc-radius-to-object.d.ts +16 -0
  95. package/lib/dist/features/2d/tarc-radius-to-object.js +58 -0
  96. package/lib/dist/features/2d/tarc-to-object.d.ts +18 -0
  97. package/lib/dist/features/2d/tarc-to-object.js +66 -0
  98. package/lib/dist/features/2d/tarc-to-point-tangent.d.ts +2 -0
  99. package/lib/dist/features/2d/tarc-to-point-tangent.js +6 -0
  100. package/lib/dist/features/2d/tarc-to-point.d.ts +2 -0
  101. package/lib/dist/features/2d/tarc-to-point.js +6 -0
  102. package/lib/dist/features/2d/tarc-with-tangent.d.ts +2 -0
  103. package/lib/dist/features/2d/tarc-with-tangent.js +6 -0
  104. package/lib/dist/features/2d/tarc.d.ts +2 -0
  105. package/lib/dist/features/2d/tarc.js +6 -0
  106. package/lib/dist/features/2d/vline.d.ts +3 -0
  107. package/lib/dist/features/2d/vline.js +9 -2
  108. package/lib/dist/features/copy-circular.d.ts +4 -3
  109. package/lib/dist/features/copy-circular.js +16 -9
  110. package/lib/dist/features/copy-circular2d.js +16 -9
  111. package/lib/dist/features/copy-linear.d.ts +4 -3
  112. package/lib/dist/features/copy-linear.js +18 -12
  113. package/lib/dist/features/copy-linear2d.js +18 -12
  114. package/lib/dist/features/extrude-base.d.ts +13 -3
  115. package/lib/dist/features/extrude-base.js +32 -3
  116. package/lib/dist/features/extrude-to-face.js +1 -5
  117. package/lib/dist/features/extrude-two-distances.js +1 -2
  118. package/lib/dist/features/extrude.js +1 -2
  119. package/lib/dist/features/mirror-feature.d.ts +3 -2
  120. package/lib/dist/features/mirror-feature.js +1 -1
  121. package/lib/dist/features/mirror-shape2d.js +2 -2
  122. package/lib/dist/features/repeat-base.d.ts +13 -0
  123. package/lib/dist/features/repeat-base.js +21 -0
  124. package/lib/dist/features/repeat-circular.d.ts +8 -7
  125. package/lib/dist/features/repeat-circular.js +7 -3
  126. package/lib/dist/features/repeat-linear.d.ts +9 -7
  127. package/lib/dist/features/repeat-linear.js +9 -3
  128. package/lib/dist/features/repeat-matrix.d.ts +3 -1
  129. package/lib/dist/features/repeat-matrix.js +7 -2
  130. package/lib/dist/features/shell.d.ts +4 -1
  131. package/lib/dist/features/shell.js +14 -3
  132. package/lib/dist/helpers/clone-transform.d.ts +2 -1
  133. package/lib/dist/index.d.ts +12 -1
  134. package/lib/dist/index.js +11 -4
  135. package/lib/dist/io/file-import.d.ts +7 -0
  136. package/lib/dist/io/file-import.js +30 -10
  137. package/lib/dist/math/lazy-matrix.d.ts +36 -0
  138. package/lib/dist/math/lazy-matrix.js +134 -0
  139. package/lib/dist/oc/boolean-ops.d.ts +2 -2
  140. package/lib/dist/oc/constraints/constraint-solver-adaptor.d.ts +5 -0
  141. package/lib/dist/oc/constraints/constraint-solver-adaptor.js +16 -0
  142. package/lib/dist/oc/constraints/constraint-solver.d.ts +4 -0
  143. package/lib/dist/oc/constraints/curve/curve-constraint-solver.d.ts +4 -0
  144. package/lib/dist/oc/constraints/curve/curve-constraint-solver.js +3 -0
  145. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.d.ts +6 -1
  146. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.js +4 -0
  147. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.d.ts +8 -0
  148. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.js +111 -0
  149. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.d.ts +8 -0
  150. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.js +161 -0
  151. package/lib/dist/oc/mesh.d.ts +9 -4
  152. package/lib/dist/oc/mesh.js +14 -13
  153. package/lib/dist/oc/shell-ops.d.ts +2 -1
  154. package/lib/dist/oc/shell-ops.js +5 -2
  155. package/lib/dist/param-registry.d.ts +34 -0
  156. package/lib/dist/param-registry.js +60 -0
  157. package/lib/dist/rendering/mesh-builder.d.ts +3 -0
  158. package/lib/dist/rendering/mesh-builder.js +10 -5
  159. package/lib/dist/rendering/render-edge.d.ts +2 -1
  160. package/lib/dist/rendering/render-edge.js +2 -2
  161. package/lib/dist/rendering/render-face.d.ts +2 -1
  162. package/lib/dist/rendering/render-face.js +2 -2
  163. package/lib/dist/rendering/render-solid.d.ts +2 -1
  164. package/lib/dist/rendering/render-solid.js +2 -2
  165. package/lib/dist/rendering/render-wire.d.ts +2 -1
  166. package/lib/dist/rendering/render-wire.js +2 -2
  167. package/lib/dist/rendering/render.d.ts +3 -0
  168. package/lib/dist/rendering/render.js +7 -2
  169. package/lib/dist/scene-manager.d.ts +4 -2
  170. package/lib/dist/scene-manager.js +12 -4
  171. package/lib/dist/tests/features/2d/arc.test.js +64 -0
  172. package/lib/dist/tests/features/2d/back.test.js +17 -1
  173. package/lib/dist/tests/features/2d/tarc.test.js +157 -0
  174. package/lib/dist/tests/features/copy-circular.test.js +1 -1
  175. package/lib/dist/tests/features/copy-linear.test.js +10 -10
  176. package/lib/dist/tests/features/repeat-user-repro-cache.test.d.ts +1 -0
  177. package/lib/dist/tests/features/repeat-user-repro-cache.test.js +97 -0
  178. package/lib/dist/tests/features/repeat-user-repro.test.d.ts +1 -0
  179. package/lib/dist/tests/features/repeat-user-repro.test.js +60 -0
  180. package/lib/dist/tests/features/shell.test.js +36 -0
  181. package/lib/dist/tests/global-setup.js +2 -1
  182. package/lib/dist/tests/helpers/extract-blocks.d.ts +9 -0
  183. package/lib/dist/tests/helpers/extract-blocks.js +56 -0
  184. package/lib/dist/tests/llm-docs-examples.test.d.ts +1 -0
  185. package/lib/dist/tests/llm-docs-examples.test.js +62 -0
  186. package/lib/dist/tests/setup.js +2 -1
  187. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  188. package/llm-docs/.coverage-allowlist.txt +9 -0
  189. package/llm-docs/api/arc.md +48 -0
  190. package/llm-docs/api/axis.md +42 -0
  191. package/llm-docs/api/bezier.md +41 -0
  192. package/llm-docs/api/booleans.md +44 -0
  193. package/llm-docs/api/chamfer.md +40 -0
  194. package/llm-docs/api/circle.md +36 -0
  195. package/llm-docs/api/color.md +34 -0
  196. package/llm-docs/api/connect.md +41 -0
  197. package/llm-docs/api/constraint-qualifiers.md +48 -0
  198. package/llm-docs/api/copy.md +63 -0
  199. package/llm-docs/api/cursor-lines.md +50 -0
  200. package/llm-docs/api/cursor-move.md +61 -0
  201. package/llm-docs/api/cut.md +55 -0
  202. package/llm-docs/api/draft.md +36 -0
  203. package/llm-docs/api/edge-filter.md +57 -0
  204. package/llm-docs/api/ellipse.md +34 -0
  205. package/llm-docs/api/extrude.md +74 -0
  206. package/llm-docs/api/face-filter.md +61 -0
  207. package/llm-docs/api/fillet.md +51 -0
  208. package/llm-docs/api/index.json +139 -0
  209. package/llm-docs/api/line.md +42 -0
  210. package/llm-docs/api/load.md +37 -0
  211. package/llm-docs/api/local.md +38 -0
  212. package/llm-docs/api/loft.md +37 -0
  213. package/llm-docs/api/mirror.md +44 -0
  214. package/llm-docs/api/offset.md +36 -0
  215. package/llm-docs/api/part.md +40 -0
  216. package/llm-docs/api/plane.md +44 -0
  217. package/llm-docs/api/polygon.md +37 -0
  218. package/llm-docs/api/primitive-solids.md +39 -0
  219. package/llm-docs/api/project-intersect.md +48 -0
  220. package/llm-docs/api/rect.md +48 -0
  221. package/llm-docs/api/remove.md +32 -0
  222. package/llm-docs/api/repeat.md +79 -0
  223. package/llm-docs/api/revolve.md +38 -0
  224. package/llm-docs/api/rib.md +40 -0
  225. package/llm-docs/api/rotate.md +37 -0
  226. package/llm-docs/api/select.md +41 -0
  227. package/llm-docs/api/shell.md +41 -0
  228. package/llm-docs/api/sketch.md +76 -0
  229. package/llm-docs/api/slot.md +36 -0
  230. package/llm-docs/api/split-trim.md +42 -0
  231. package/llm-docs/api/sweep.md +43 -0
  232. package/llm-docs/api/tarc.md +45 -0
  233. package/llm-docs/api/tcircle.md +38 -0
  234. package/llm-docs/api/tline.md +42 -0
  235. package/llm-docs/api/translate.md +40 -0
  236. package/llm-docs/api/types/aline.md +35 -0
  237. package/llm-docs/api/types/arc-angles.md +29 -0
  238. package/llm-docs/api/types/arc-points.md +48 -0
  239. package/llm-docs/api/types/axis-like.md +38 -0
  240. package/llm-docs/api/types/axis.md +21 -0
  241. package/llm-docs/api/types/boolean-operation.md +50 -0
  242. package/llm-docs/api/types/circular-repeat-options.md +31 -0
  243. package/llm-docs/api/types/common.md +32 -0
  244. package/llm-docs/api/types/cut.md +125 -0
  245. package/llm-docs/api/types/draft.md +21 -0
  246. package/llm-docs/api/types/extrudable-geometry.md +23 -0
  247. package/llm-docs/api/types/extrude.md +194 -0
  248. package/llm-docs/api/types/geometry.md +51 -0
  249. package/llm-docs/api/types/hline.md +35 -0
  250. package/llm-docs/api/types/linear-repeat-options.md +31 -0
  251. package/llm-docs/api/types/loft.md +154 -0
  252. package/llm-docs/api/types/mirror.md +35 -0
  253. package/llm-docs/api/types/offset.md +31 -0
  254. package/llm-docs/api/types/plane-like.md +35 -0
  255. package/llm-docs/api/types/plane-transform-options.md +29 -0
  256. package/llm-docs/api/types/plane.md +21 -0
  257. package/llm-docs/api/types/point-like.md +22 -0
  258. package/llm-docs/api/types/point2dlike.md +26 -0
  259. package/llm-docs/api/types/polygon.md +46 -0
  260. package/llm-docs/api/types/rect.md +128 -0
  261. package/llm-docs/api/types/revolve.md +102 -0
  262. package/llm-docs/api/types/rib.md +133 -0
  263. package/llm-docs/api/types/scene-object.md +33 -0
  264. package/llm-docs/api/types/select.md +21 -0
  265. package/llm-docs/api/types/shell.md +54 -0
  266. package/llm-docs/api/types/slot.md +43 -0
  267. package/llm-docs/api/types/sweep.md +189 -0
  268. package/llm-docs/api/types/tangent-arc-two-objects.md +46 -0
  269. package/llm-docs/api/types/transformable.md +93 -0
  270. package/llm-docs/api/types/trim.md +27 -0
  271. package/llm-docs/api/types/two-objects-tangent-line.md +46 -0
  272. package/llm-docs/api/types/vertex.md +17 -0
  273. package/llm-docs/api/types/vline.md +35 -0
  274. package/llm-docs/concepts/coordinate-system.md +45 -0
  275. package/llm-docs/concepts/history-and-rollback.md +40 -0
  276. package/llm-docs/concepts/last-selection.md +49 -0
  277. package/llm-docs/concepts/scene-graph.md +37 -0
  278. package/llm-docs/index.json +1750 -0
  279. package/mcp/dist/client.d.ts +65 -0
  280. package/mcp/dist/client.js +255 -0
  281. package/mcp/dist/discovery.d.ts +11 -0
  282. package/mcp/dist/discovery.js +78 -0
  283. package/mcp/dist/docs-index.d.ts +81 -0
  284. package/mcp/dist/docs-index.js +261 -0
  285. package/mcp/dist/resources.d.ts +4 -0
  286. package/mcp/dist/resources.js +115 -0
  287. package/mcp/dist/server.d.ts +12 -0
  288. package/mcp/dist/server.js +502 -0
  289. package/mcp/dist/tools/coordination.d.ts +9 -0
  290. package/mcp/dist/tools/coordination.js +46 -0
  291. package/mcp/dist/tools/docs.d.ts +66 -0
  292. package/mcp/dist/tools/docs.js +122 -0
  293. package/mcp/dist/tools/engine.d.ts +72 -0
  294. package/mcp/dist/tools/engine.js +190 -0
  295. package/mcp/dist/tools/inspection.d.ts +75 -0
  296. package/mcp/dist/tools/inspection.js +121 -0
  297. package/mcp/dist/tools/screenshot.d.ts +63 -0
  298. package/mcp/dist/tools/screenshot.js +263 -0
  299. package/mcp/dist/tools/source.d.ts +84 -0
  300. package/mcp/dist/tools/source.js +434 -0
  301. package/mcp/dist/tools/workspaces.d.ts +13 -0
  302. package/mcp/dist/tools/workspaces.js +33 -0
  303. package/mcp/dist/types.d.ts +18 -0
  304. package/mcp/dist/types.js +11 -0
  305. package/package.json +27 -7
  306. package/server/dist/api.d.ts +37 -0
  307. package/server/dist/api.js +44 -0
  308. package/server/dist/code-editor.d.ts +100 -0
  309. package/server/dist/code-editor.js +528 -2
  310. package/server/dist/fluidcad-server.d.ts +118 -1
  311. package/server/dist/fluidcad-server.js +350 -62
  312. package/server/dist/global-registry.d.ts +30 -0
  313. package/server/dist/global-registry.js +126 -0
  314. package/server/dist/host/blocked-imports.d.ts +8 -0
  315. package/server/dist/host/blocked-imports.js +30 -0
  316. package/server/dist/{vite-manager.d.ts → host/local-scene-host.d.ts} +3 -1
  317. package/server/dist/{vite-manager.js → host/local-scene-host.js} +6 -26
  318. package/server/dist/host/scene-host.d.ts +19 -0
  319. package/server/dist/host/scene-host.js +1 -0
  320. package/server/dist/index.js +175 -123
  321. package/server/dist/instance-file.d.ts +31 -0
  322. package/server/dist/instance-file.js +73 -0
  323. package/server/dist/lint-fluid-js.d.ts +15 -0
  324. package/server/dist/lint-fluid-js.js +271 -0
  325. package/server/dist/model-package/capture-params.d.ts +19 -0
  326. package/server/dist/model-package/capture-params.js +42 -0
  327. package/server/dist/model-package/pack.d.ts +23 -0
  328. package/server/dist/model-package/pack.js +229 -0
  329. package/server/dist/model-package/types.d.ts +78 -0
  330. package/server/dist/model-package/types.js +17 -0
  331. package/server/dist/routes/editor.d.ts +24 -0
  332. package/server/dist/routes/editor.js +44 -0
  333. package/server/dist/routes/export.d.ts +1 -1
  334. package/server/dist/routes/export.js +45 -8
  335. package/server/dist/routes/health.d.ts +7 -0
  336. package/server/dist/routes/health.js +14 -0
  337. package/server/dist/routes/hit-test.d.ts +3 -0
  338. package/server/dist/routes/hit-test.js +17 -0
  339. package/server/dist/routes/lint.d.ts +10 -0
  340. package/server/dist/routes/lint.js +28 -0
  341. package/server/dist/routes/pack.d.ts +10 -0
  342. package/server/dist/routes/pack.js +47 -0
  343. package/server/dist/routes/params.d.ts +3 -0
  344. package/server/dist/routes/params.js +75 -0
  345. package/server/dist/routes/render.d.ts +33 -0
  346. package/server/dist/routes/render.js +34 -0
  347. package/server/dist/routes/scene.d.ts +5 -0
  348. package/server/dist/routes/scene.js +48 -0
  349. package/server/dist/routes/screenshot.js +68 -1
  350. package/server/dist/routes/sketch-edits.d.ts +3 -0
  351. package/server/dist/routes/sketch-edits.js +542 -0
  352. package/server/dist/routes/timeline.d.ts +3 -0
  353. package/server/dist/routes/timeline.js +49 -0
  354. package/server/dist/server-core.d.ts +53 -0
  355. package/server/dist/server-core.js +147 -0
  356. package/server/dist/ws-protocol.d.ts +156 -3
  357. package/ui/dist/assets/index-CDJmUpFI.css +2 -0
  358. package/ui/dist/assets/index-MRqwG9Vh.js +5417 -0
  359. package/ui/dist/index.html +2 -2
  360. package/server/dist/routes/actions.d.ts +0 -3
  361. package/server/dist/routes/actions.js +0 -309
  362. package/ui/dist/assets/index-CFi9p7wR.js +0 -4946
  363. package/ui/dist/assets/index-DR7c2Qk9.css +0 -2
@@ -9,6 +9,7 @@ import { Point2DLike } from "../math/point.js";
9
9
  import { Plane } from "../math/plane.js";
10
10
  import { FaceFilterBuilder } from "../filters/face/face-filter.js";
11
11
  import { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
12
+ import { type NumberParam } from "../core/param.js";
12
13
  import { ShapeHistory } from "../common/shape-history-tracker.js";
13
14
  /** A 3D op's classified face buckets. Each is empty if the op doesn't produce that category. */
14
15
  export type ClassifiedFaces = {
@@ -32,6 +33,15 @@ export declare abstract class ExtrudeBase extends SceneObject implements IExtrud
32
33
  get faceSource(): SceneObject | null;
33
34
  isFaceSourced(): boolean;
34
35
  getSource(): SceneObject | null;
36
+ /**
37
+ * Dependency tail for cloning: if the source is a sketch-bound geometry
38
+ * primitive, return its containing `Sketch` so cloneWithTransform pulls
39
+ * the sketch in too. The sketch's clone-mode build path then carries
40
+ * correctly-transformed shapes onto cloned children, and the cloned
41
+ * primitive retains a `Sketch` parent for plane resolution. Otherwise
42
+ * return the source as-is.
43
+ */
44
+ protected getSourceDependencies(): SceneObject[];
35
45
  getSourcePlane(): Plane | null;
36
46
  getSourceFaces(): Face[];
37
47
  startFaces(...args: number[] | FaceFilterBuilder[]): SceneObject;
@@ -96,10 +106,10 @@ export declare abstract class ExtrudeBase extends SceneObject implements IExtrud
96
106
  private buildSuffix;
97
107
  private resolveFaces;
98
108
  private resolveEdges;
99
- draft(value: number | [number, number]): this;
100
- endOffset(value: number): this;
109
+ draft(value: NumberParam | [NumberParam, NumberParam]): this;
110
+ endOffset(value: NumberParam): this;
101
111
  drill(value?: boolean): this;
102
- thin(offset1: number, offset2?: number): this;
112
+ thin(offset1: NumberParam, offset2?: NumberParam): this;
103
113
  isThin(): boolean;
104
114
  getThinOffsets(): [number] | [number, number] | undefined;
105
115
  protected serializePickFields(): {
@@ -2,6 +2,7 @@ import { Face } from "../common/face.js";
2
2
  import { Edge } from "../common/edge.js";
3
3
  import { SceneObject } from "../common/scene-object.js";
4
4
  import { LazySelectionSceneObject } from "./lazy-scene-object.js";
5
+ import { GeometrySceneObject } from "./2d/geometry.js";
5
6
  import { normalizePoint2D } from "../helpers/normalize.js";
6
7
  import { FaceOps } from "../oc/face-ops.js";
7
8
  import { FaceMaker2 } from "../oc/face-maker2.js";
@@ -10,6 +11,7 @@ import { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
10
11
  import { ShapeFilter } from "../filters/filter.js";
11
12
  import { EdgeOps } from "../oc/edge-ops.js";
12
13
  import { Explorer } from "../oc/explorer.js";
14
+ import { resolveParam } from "../core/param.js";
13
15
  import { getOC } from "../oc/init.js";
14
16
  import { ShapeHistoryTracker } from "../common/shape-history-tracker.js";
15
17
  import { fuseWithSceneObjects } from "../helpers/scene-helpers.js";
@@ -81,6 +83,27 @@ export class ExtrudeBase extends SceneObject {
81
83
  getSource() {
82
84
  return this._extrudable ?? this._faceSource;
83
85
  }
86
+ /**
87
+ * Dependency tail for cloning: if the source is a sketch-bound geometry
88
+ * primitive, return its containing `Sketch` so cloneWithTransform pulls
89
+ * the sketch in too. The sketch's clone-mode build path then carries
90
+ * correctly-transformed shapes onto cloned children, and the cloned
91
+ * primitive retains a `Sketch` parent for plane resolution. Otherwise
92
+ * return the source as-is.
93
+ */
94
+ getSourceDependencies() {
95
+ const source = this.getSource();
96
+ if (!source) {
97
+ return [];
98
+ }
99
+ if (source instanceof GeometrySceneObject) {
100
+ const sketch = source.sketch;
101
+ if (sketch) {
102
+ return [sketch];
103
+ }
104
+ }
105
+ return [source];
106
+ }
84
107
  getSourcePlane() {
85
108
  if (this._extrudable) {
86
109
  return this._extrudable.getPlane();
@@ -376,11 +399,16 @@ export class ExtrudeBase extends SceneObject {
376
399
  return new ShapeFilter(shapes, ...filters).apply();
377
400
  }
378
401
  draft(value) {
379
- this._draft = value;
402
+ if (Array.isArray(value)) {
403
+ this._draft = [resolveParam(value[0]), resolveParam(value[1])];
404
+ }
405
+ else {
406
+ this._draft = resolveParam(value);
407
+ }
380
408
  return this;
381
409
  }
382
410
  endOffset(value) {
383
- this._endOffset = value;
411
+ this._endOffset = resolveParam(value);
384
412
  return this;
385
413
  }
386
414
  drill(value = true) {
@@ -388,7 +416,8 @@ export class ExtrudeBase extends SceneObject {
388
416
  return this;
389
417
  }
390
418
  thin(offset1, offset2) {
391
- this._thin = offset2 !== undefined ? [offset1, offset2] : [offset1];
419
+ const o1 = resolveParam(offset1);
420
+ this._thin = offset2 !== undefined ? [o1, resolveParam(offset2)] : [o1];
392
421
  return this;
393
422
  }
394
423
  isThin() {
@@ -282,11 +282,7 @@ export class ExtrudeToFace extends ExtrudeBase {
282
282
  return objects;
283
283
  }
284
284
  getDependencies() {
285
- const deps = [];
286
- const source = this.getSource();
287
- if (source) {
288
- deps.push(source);
289
- }
285
+ const deps = [...this.getSourceDependencies()];
290
286
  if (this.face instanceof SceneObject) {
291
287
  deps.push(this.face);
292
288
  }
@@ -158,8 +158,7 @@ export class ExtrudeTwoDistances extends ExtrudeBase {
158
158
  this.setFinalShapes(this.getShapes());
159
159
  }
160
160
  getDependencies() {
161
- const source = this.getSource();
162
- return source ? [source] : [];
161
+ return this.getSourceDependencies();
163
162
  }
164
163
  createCopy(remap) {
165
164
  const source = this.getSource();
@@ -286,8 +286,7 @@ export class Extrude extends ExtrudeBase {
286
286
  });
287
287
  }
288
288
  getDependencies() {
289
- const source = this.getSource();
290
- return source ? [source] : [];
289
+ return this.getSourceDependencies();
291
290
  }
292
291
  createCopy(remap) {
293
292
  const source = this.getSource();
@@ -1,10 +1,11 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
2
  import { Matrix4 } from "../math/matrix4.js";
3
+ import { LazyMatrix } from "../math/lazy-matrix.js";
3
4
  import { PlaneObjectBase } from "./plane-renderable-base.js";
4
5
  export declare class MirrorFeature extends SceneObject {
5
6
  private plane;
6
- private _matrix?;
7
- constructor(plane: PlaneObjectBase, _matrix?: Matrix4);
7
+ private _matrix;
8
+ constructor(plane: PlaneObjectBase, _matrix: LazyMatrix);
8
9
  getTransformMatrix(): Matrix4 | null;
9
10
  isContainer(): boolean;
10
11
  build(context: BuildSceneObjectContext): void;
@@ -9,7 +9,7 @@ export class MirrorFeature extends SceneObject {
9
9
  this.setAlwaysVisible();
10
10
  }
11
11
  getTransformMatrix() {
12
- return this._matrix || null;
12
+ return this._matrix.resolve();
13
13
  }
14
14
  isContainer() {
15
15
  return true;
@@ -44,8 +44,8 @@ export class MirrorShape2D extends GeometrySceneObject {
44
44
  transformedShapes.push(transformed);
45
45
  }
46
46
  }
47
- const firstShape = transformedShapes[0];
48
- const lastShape = transformedShapes[transformedShapes.length - 1];
47
+ const firstShape = transformedShapes.find(shape => !shape.isMetaShape() && !shape.isGuideShape());
48
+ const lastShape = transformedShapes.toReversed().find(shape => !shape.isMetaShape() && !shape.isGuideShape());
49
49
  if (firstShape) {
50
50
  const start = firstShape.getFirstVertex();
51
51
  if (start) {
@@ -0,0 +1,13 @@
1
+ import { SceneObject } from "../common/scene-object.js";
2
+ import { Axis } from "../math/axis.js";
3
+ import { AxisObjectBase } from "./axis-renderable-base.js";
4
+ export type RepeatAxisSource = Axis | AxisObjectBase;
5
+ /**
6
+ * Shared base for repeat features. Holds structural equality helpers used
7
+ * by `compareTo`, which runs during cache-compare — before any render —
8
+ * when an `AxisObjectBase` source may not yet have its resolved `Axis`
9
+ * state. Comparing via `getAxis()` at that point would NPE.
10
+ */
11
+ export declare abstract class RepeatBase extends SceneObject {
12
+ protected static axisSourceEquals(a: RepeatAxisSource, b: RepeatAxisSource): boolean;
13
+ }
@@ -0,0 +1,21 @@
1
+ import { SceneObject } from "../common/scene-object.js";
2
+ import { AxisObjectBase } from "./axis-renderable-base.js";
3
+ /**
4
+ * Shared base for repeat features. Holds structural equality helpers used
5
+ * by `compareTo`, which runs during cache-compare — before any render —
6
+ * when an `AxisObjectBase` source may not yet have its resolved `Axis`
7
+ * state. Comparing via `getAxis()` at that point would NPE.
8
+ */
9
+ export class RepeatBase extends SceneObject {
10
+ static axisSourceEquals(a, b) {
11
+ const aObj = a instanceof AxisObjectBase;
12
+ const bObj = b instanceof AxisObjectBase;
13
+ if (aObj !== bObj) {
14
+ return false;
15
+ }
16
+ if (aObj) {
17
+ return a.compareTo(b);
18
+ }
19
+ return a.equals(b);
20
+ }
21
+ }
@@ -1,21 +1,22 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
- import { Axis } from "../math/axis.js";
2
+ import { RepeatBase, RepeatAxisSource } from "./repeat-base.js";
3
+ import { type NumberParam } from "../core/param.js";
3
4
  export type CircularRepeatOptions = {
4
- count: number;
5
+ count: NumberParam;
5
6
  centered?: boolean;
6
7
  skip?: number[];
7
8
  } & ({
8
- offset: number;
9
+ offset: NumberParam;
9
10
  angle?: never;
10
11
  } | {
11
- angle: number;
12
+ angle: NumberParam;
12
13
  offset?: never;
13
14
  });
14
- export declare class RepeatCircular extends SceneObject {
15
- axis: Axis;
15
+ export declare class RepeatCircular extends RepeatBase {
16
+ axis: RepeatAxisSource;
16
17
  options: CircularRepeatOptions;
17
18
  targetObjects: SceneObject[] | null;
18
- constructor(axis: Axis, options: CircularRepeatOptions, targetObjects?: SceneObject[] | null);
19
+ constructor(axis: RepeatAxisSource, options: CircularRepeatOptions, targetObjects?: SceneObject[] | null);
19
20
  isContainer(): boolean;
20
21
  build(context: BuildSceneObjectContext): void;
21
22
  compareTo(other: RepeatCircular): boolean;
@@ -1,5 +1,6 @@
1
- import { SceneObject } from "../common/scene-object.js";
2
- export class RepeatCircular extends SceneObject {
1
+ import { AxisObjectBase } from "./axis-renderable-base.js";
2
+ import { RepeatBase } from "./repeat-base.js";
3
+ export class RepeatCircular extends RepeatBase {
3
4
  axis;
4
5
  options;
5
6
  targetObjects;
@@ -14,6 +15,9 @@ export class RepeatCircular extends SceneObject {
14
15
  return true;
15
16
  }
16
17
  build(context) {
18
+ if (this.axis instanceof AxisObjectBase) {
19
+ this.axis.removeShapes(this);
20
+ }
17
21
  this.saveShapesSnapshot(context);
18
22
  }
19
23
  compareTo(other) {
@@ -23,7 +27,7 @@ export class RepeatCircular extends SceneObject {
23
27
  if (!super.compareTo(other)) {
24
28
  return false;
25
29
  }
26
- if (!this.axis.equals(other.axis)) {
30
+ if (!RepeatCircular.axisSourceEquals(this.axis, other.axis)) {
27
31
  return false;
28
32
  }
29
33
  const thisTargetObjects = this.targetObjects || [];
@@ -1,21 +1,23 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
- import { Axis } from "../math/axis.js";
2
+ import { RepeatBase, RepeatAxisSource } from "./repeat-base.js";
3
+ export { RepeatAxisSource } from "./repeat-base.js";
4
+ import { type NumberParam } from "../core/param.js";
3
5
  export type LinearRepeatOptions = {
4
- count: number | number[];
6
+ count: NumberParam | number[];
5
7
  centered?: boolean;
6
8
  skip?: number[][];
7
9
  } & ({
8
- offset: number | number[];
10
+ offset: NumberParam | number[];
9
11
  length?: never;
10
12
  } | {
11
- length: number | number[];
13
+ length: NumberParam | number[];
12
14
  offset?: never;
13
15
  });
14
- export declare class RepeatLinear extends SceneObject {
15
- axes: Axis[];
16
+ export declare class RepeatLinear extends RepeatBase {
17
+ axes: RepeatAxisSource[];
16
18
  options: LinearRepeatOptions;
17
19
  targetObjects: SceneObject[] | null;
18
- constructor(axes: Axis[], options: LinearRepeatOptions, targetObjects?: SceneObject[] | null);
20
+ constructor(axes: RepeatAxisSource[], options: LinearRepeatOptions, targetObjects?: SceneObject[] | null);
19
21
  isContainer(): boolean;
20
22
  build(context: BuildSceneObjectContext): void;
21
23
  compareTo(other: RepeatLinear): boolean;
@@ -1,5 +1,6 @@
1
- import { SceneObject } from "../common/scene-object.js";
2
- export class RepeatLinear extends SceneObject {
1
+ import { AxisObjectBase } from "./axis-renderable-base.js";
2
+ import { RepeatBase } from "./repeat-base.js";
3
+ export class RepeatLinear extends RepeatBase {
3
4
  axes;
4
5
  options;
5
6
  targetObjects;
@@ -14,6 +15,11 @@ export class RepeatLinear extends SceneObject {
14
15
  return true;
15
16
  }
16
17
  build(context) {
18
+ for (const axis of this.axes) {
19
+ if (axis instanceof AxisObjectBase) {
20
+ axis.removeShapes(this);
21
+ }
22
+ }
17
23
  this.saveShapesSnapshot(context);
18
24
  }
19
25
  compareTo(other) {
@@ -27,7 +33,7 @@ export class RepeatLinear extends SceneObject {
27
33
  return false;
28
34
  }
29
35
  for (let i = 0; i < this.axes.length; i++) {
30
- if (!this.axes[i].equals(other.axes[i])) {
36
+ if (!RepeatLinear.axisSourceEquals(this.axes[i], other.axes[i])) {
31
37
  return false;
32
38
  }
33
39
  }
@@ -1,9 +1,11 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
2
  import { Matrix4 } from "../math/matrix4.js";
3
+ import { LazyMatrix } from "../math/lazy-matrix.js";
3
4
  export declare class RepeatMatrix extends SceneObject {
4
5
  private _matrix;
5
6
  targetObjects: SceneObject[];
6
- constructor(_matrix: Matrix4, targetObjects: SceneObject[]);
7
+ private sources;
8
+ constructor(_matrix: LazyMatrix, targetObjects: SceneObject[], sources?: SceneObject[]);
7
9
  getTransformMatrix(): Matrix4 | null;
8
10
  isContainer(): boolean;
9
11
  build(context: BuildSceneObjectContext): void;
@@ -2,19 +2,24 @@ import { SceneObject } from "../common/scene-object.js";
2
2
  export class RepeatMatrix extends SceneObject {
3
3
  _matrix;
4
4
  targetObjects;
5
- constructor(_matrix, targetObjects) {
5
+ sources;
6
+ constructor(_matrix, targetObjects, sources = []) {
6
7
  super();
7
8
  this._matrix = _matrix;
8
9
  this.targetObjects = targetObjects;
10
+ this.sources = sources;
9
11
  this.setAlwaysVisible();
10
12
  }
11
13
  getTransformMatrix() {
12
- return this._matrix;
14
+ return this._matrix.resolve();
13
15
  }
14
16
  isContainer() {
15
17
  return true;
16
18
  }
17
19
  build(context) {
20
+ for (const source of this.sources) {
21
+ source.removeShapes(this);
22
+ }
18
23
  this.saveShapesSnapshot(context);
19
24
  }
20
25
  compareTo(other) {
@@ -2,12 +2,14 @@ import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js"
2
2
  import { SelectSceneObject } from "./select.js";
3
3
  import { FaceFilterBuilder } from "../filters/face/face-filter.js";
4
4
  import { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
5
- import { IShell } from "../core/interfaces.js";
5
+ import { IShell, ShellJoinType } from "../core/interfaces.js";
6
6
  export declare class Shell extends SceneObject implements IShell {
7
7
  private thickness;
8
8
  private _faceSelections;
9
+ private _joinType;
9
10
  constructor(thickness: number, faceSelections?: SelectSceneObject[]);
10
11
  get faceSelections(): SelectSceneObject[];
12
+ join(type: ShellJoinType): this;
11
13
  validate(): void;
12
14
  build(context: BuildSceneObjectContext): void;
13
15
  internalFaces(...args: (number | FaceFilterBuilder)[]): SceneObject;
@@ -21,5 +23,6 @@ export declare class Shell extends SceneObject implements IShell {
21
23
  getType(): string;
22
24
  serialize(): {
23
25
  thickness: number;
26
+ joinType: "intersection" | "tangent";
24
27
  };
25
28
  }
@@ -11,6 +11,7 @@ import { requireShapes } from "../common/operand-check.js";
11
11
  export class Shell extends SceneObject {
12
12
  thickness;
13
13
  _faceSelections = [];
14
+ _joinType = 'arc';
14
15
  constructor(thickness, faceSelections) {
15
16
  super();
16
17
  this.thickness = thickness;
@@ -19,6 +20,10 @@ export class Shell extends SceneObject {
19
20
  get faceSelections() {
20
21
  return this._faceSelections;
21
22
  }
23
+ join(type) {
24
+ this._joinType = type;
25
+ return this;
26
+ }
22
27
  validate() {
23
28
  for (let i = 0; i < this._faceSelections.length; i++) {
24
29
  requireShapes(this._faceSelections[i], `face selection ${i + 1}`, "shell");
@@ -52,7 +57,7 @@ export class Shell extends SceneObject {
52
57
  continue;
53
58
  }
54
59
  try {
55
- const newShape = ShellOps.makeThickSolid(shape, targetFaces, this.thickness);
60
+ const newShape = ShellOps.makeThickSolid(shape, targetFaces, this.thickness, this._joinType);
56
61
  newShapes.push(newShape);
57
62
  const originalObj = shapeObjMap.get(shape);
58
63
  originalObj.removeShape(shape, this);
@@ -192,6 +197,9 @@ export class Shell extends SceneObject {
192
197
  if (this.thickness !== other.thickness) {
193
198
  return false;
194
199
  }
200
+ if (this._joinType !== other._joinType) {
201
+ return false;
202
+ }
195
203
  if (this._faceSelections.length !== other._faceSelections.length) {
196
204
  return false;
197
205
  }
@@ -207,14 +215,17 @@ export class Shell extends SceneObject {
207
215
  }
208
216
  createCopy(remap) {
209
217
  const faceSelections = this._faceSelections.map(sel => (remap.get(sel) || sel));
210
- return new Shell(this.thickness, faceSelections.length > 0 ? faceSelections : undefined);
218
+ const copy = new Shell(this.thickness, faceSelections.length > 0 ? faceSelections : undefined);
219
+ copy._joinType = this._joinType;
220
+ return copy;
211
221
  }
212
222
  getType() {
213
223
  return 'shell';
214
224
  }
215
225
  serialize() {
216
226
  return {
217
- thickness: this.thickness
227
+ thickness: this.thickness,
228
+ joinType: this._joinType !== 'arc' ? this._joinType : undefined
218
229
  };
219
230
  }
220
231
  }
@@ -1,3 +1,4 @@
1
1
  import { Matrix4 } from "../math/matrix4.js";
2
+ import { LazyMatrix } from "../math/lazy-matrix.js";
2
3
  import { SceneObject } from "../common/scene-object.js";
3
- export declare function cloneWithTransform(objects: SceneObject[], transform: Matrix4, container: SceneObject): SceneObject[];
4
+ export declare function cloneWithTransform(objects: SceneObject[], transform: Matrix4 | LazyMatrix, container: SceneObject): SceneObject[];
@@ -17,7 +17,18 @@ export type SceneParserContext = {
17
17
  getActiveSketch(): Sketch | null;
18
18
  };
19
19
  export declare function registerBuilder<T extends Function>(builder: (context: SceneParserContext) => T): T;
20
- export declare function init(rootPath?: string): Promise<{
20
+ export { createParamRegistry, getParamRegistry } from './param-registry.js';
21
+ export type { ParamDefinition, MultiControlType, SelectOption, ParamVal, ParamScalar } from './param-registry.js';
22
+ export { setAssetProvider } from './io/file-import.js';
23
+ export type { AssetProvider } from './io/file-import.js';
24
+ export { getSceneManager } from './scene-manager.js';
25
+ export interface FluidCADOptions {
26
+ mesh?: {
27
+ lineDeflection?: number;
28
+ angularDeflection?: number;
29
+ };
30
+ }
31
+ export declare function init(options?: FluidCADOptions): Promise<{
21
32
  currentScene: Scene;
22
33
  currentFile: string;
23
34
  renderer: import("./rendering/render.js").SceneRenderer;
package/lib/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { loadOC } from "./load.js";
2
- import { createManager, getCurrentScene } from "./scene-manager.js";
2
+ import { createManager, getCurrentScene, getSceneManager } from "./scene-manager.js";
3
3
  import { parse as parseStackTrace } from "stacktrace-parser";
4
4
  export function captureSourceLocation() {
5
5
  const stack = new Error().stack;
@@ -88,8 +88,15 @@ export function registerBuilder(builder) {
88
88
  return fn;
89
89
  ;
90
90
  }
91
- export async function init(rootPath) {
91
+ export { createParamRegistry, getParamRegistry } from './param-registry.js';
92
+ export { setAssetProvider } from './io/file-import.js';
93
+ export { getSceneManager } from './scene-manager.js';
94
+ export async function init(options) {
92
95
  await loadOC();
93
- const resolvedPath = rootPath || process.env.FLUIDCAD_WORKSPACE_PATH || '';
94
- return createManager(resolvedPath);
96
+ const existing = getSceneManager();
97
+ if (existing) {
98
+ return existing;
99
+ }
100
+ const resolvedPath = process.env.FLUIDCAD_WORKSPACE_PATH || '';
101
+ return createManager(resolvedPath, options);
95
102
  }
@@ -1,5 +1,12 @@
1
1
  import { Shape } from "../common/shape.js";
2
2
  import { Solid } from "../common/solid.js";
3
+ /**
4
+ * Override hook for hub mode (and tests). When set, asset reads consult
5
+ * the provider instead of the filesystem — paths are workspace-relative
6
+ * (e.g. `imports/foo.brep`). Returning null falls back to disk.
7
+ */
8
+ export type AssetProvider = (workspaceRelPath: string) => Uint8Array | null;
9
+ export declare function setAssetProvider(provider: AssetProvider | null): void;
3
10
  export declare class FileImport {
4
11
  static deserializeShapes(fileName: string): Solid[];
5
12
  static serializeShape(shape: Shape, workspacePath: string, fileName: string): void;
@@ -2,17 +2,37 @@ import * as fs from "fs";
2
2
  import { join } from "path";
3
3
  import { OcIO } from "../oc/io.js";
4
4
  import { getSceneManager } from "../scene-manager.js";
5
+ let assetProvider = null;
6
+ export function setAssetProvider(provider) {
7
+ assetProvider = provider;
8
+ }
9
+ function readWorkspaceAsset(relPath) {
10
+ if (assetProvider) {
11
+ const bytes = assetProvider(relPath);
12
+ if (bytes) {
13
+ return { text: Buffer.from(bytes).toString('utf8'), exists: true };
14
+ }
15
+ }
16
+ const sceneManager = getSceneManager();
17
+ const filePath = join(sceneManager.rootPath, relPath);
18
+ if (!fs.existsSync(filePath)) {
19
+ return { exists: false };
20
+ }
21
+ return { text: fs.readFileSync(filePath, 'utf8'), exists: true };
22
+ }
5
23
  export class FileImport {
6
24
  static deserializeShapes(fileName) {
7
25
  if (!fileName.endsWith(('.brep'))) {
8
26
  fileName += '.brep';
9
27
  }
10
- const sceneManager = getSceneManager();
11
- const filePath = join(sceneManager.rootPath, 'imports', fileName);
28
+ const relPath = join('imports', fileName);
12
29
  console.log(`Reading file ${fileName}`);
13
- const file = fs.readFileSync(filePath, 'utf8');
14
- console.log(`File ${filePath} read successfully, size: ${file.length} bytes`);
15
- return OcIO.readBRepSolids(fileName, file);
30
+ const result = readWorkspaceAsset(relPath);
31
+ if (!result.exists) {
32
+ throw new Error(`Imported asset not found: ${relPath}`);
33
+ }
34
+ console.log(`File ${relPath} read successfully, size: ${result.text.length} bytes`);
35
+ return OcIO.readBRepSolids(fileName, result.text);
16
36
  }
17
37
  static serializeShape(shape, workspacePath, fileName) {
18
38
  const file = OcIO.writeBRep(shape, fileName);
@@ -56,11 +76,11 @@ export class FileImport {
56
76
  // Read color metadata from JSON sidecar (skipped when noColors is set)
57
77
  let colorData = [];
58
78
  if (!options?.noColors) {
59
- const sceneManager = getSceneManager();
60
- const jsonPath = join(sceneManager.rootPath, 'imports', brepFileName + '.colors.json');
61
- if (fs.existsSync(jsonPath)) {
62
- colorData = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
63
- console.log(`Loaded color metadata from ${jsonPath}`);
79
+ const relPath = join('imports', brepFileName + '.colors.json');
80
+ const result = readWorkspaceAsset(relPath);
81
+ if (result.exists) {
82
+ colorData = JSON.parse(result.text);
83
+ console.log(`Loaded color metadata from ${relPath}`);
64
84
  }
65
85
  }
66
86
  const include = options?.include;
@@ -0,0 +1,36 @@
1
+ import { Matrix4 } from "./matrix4.js";
2
+ import { Axis } from "./axis.js";
3
+ import { Plane } from "./plane.js";
4
+ /** Anything that can be resolved to an `Axis` once built — e.g. `AxisObjectBase`. */
5
+ export interface AxisLazySource {
6
+ getAxis(): Axis;
7
+ compareTo?(other: unknown): boolean;
8
+ }
9
+ /** Anything that can be resolved to a `Plane` once built — e.g. `PlaneObjectBase`. */
10
+ export interface PlaneLazySource {
11
+ getPlane(): Plane;
12
+ compareTo?(other: unknown): boolean;
13
+ }
14
+ /**
15
+ * Memoized thunk over a Matrix4. Lets parse-time code thread a transform
16
+ * value that depends on scene state (e.g. an AxisObjectBase or
17
+ * PlaneObjectBase) before that state exists. Resolution is deferred to the
18
+ * first call to `resolve()`, by which point the renderer has built the source
19
+ * object. Concrete `Axis` / `Plane` sources resolve eagerly with no extra
20
+ * indirection.
21
+ */
22
+ export declare class LazyMatrix {
23
+ private _resolver;
24
+ private _cached;
25
+ private _identity;
26
+ private constructor();
27
+ resolve(): Matrix4;
28
+ equals(other: LazyMatrix, tolerance?: number): boolean;
29
+ private static axisSourceEquals;
30
+ private static planeSourceEquals;
31
+ static of(matrix: Matrix4): LazyMatrix;
32
+ static from(resolver: () => Matrix4): LazyMatrix;
33
+ static mirror(plane: Plane | PlaneLazySource): LazyMatrix;
34
+ static rotation(axis: Axis | AxisLazySource, angle: number): LazyMatrix;
35
+ static translation(axis: Axis | AxisLazySource, distance: number): LazyMatrix;
36
+ }