@things-factory/figure-ui 10.1.75 → 10.1.77

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 (282) hide show
  1. package/client/figure-assistant.ts +3 -3
  2. package/client/graphql/{v3-store.ts → store.ts} +6 -6
  3. package/client/modeller/{v3-ai-proposal.ts → ai-proposal.ts} +8 -8
  4. package/client/modeller/{v3-align.ts → align.ts} +14 -14
  5. package/client/modeller/{v3-canvas.ts → canvas.ts} +13 -13
  6. package/client/modeller/{v3-clips.ts → clips.ts} +5 -5
  7. package/client/modeller/{v3-controls.ts → controls.ts} +2 -2
  8. package/client/modeller/{v3-editor.ts → editor.ts} +117 -117
  9. package/client/modeller/{figure-v3-capability.ts → figure-capability-panel.ts} +7 -7
  10. package/client/modeller/{figure-v3-clips.ts → figure-clips.ts} +10 -10
  11. package/client/modeller/{figure-v3-controls.ts → figure-controls.ts} +9 -9
  12. package/client/modeller/{v3-figure-facts.ts → figure-facts.ts} +11 -11
  13. package/client/modeller/{figure-v3-first-save.ts → figure-first-save.ts} +3 -3
  14. package/client/modeller/figure-history-panel.ts +1 -1
  15. package/client/modeller/{figure-v3-links.ts → figure-links.ts} +35 -35
  16. package/client/modeller/{figure-v3-material.ts → figure-material-panel.ts} +20 -20
  17. package/client/modeller/{figure-v3-parts.ts → figure-parts.ts} +15 -15
  18. package/client/modeller/{figure-v3-preview.ts → figure-preview.ts} +14 -14
  19. package/client/modeller/{figure-v3-properties.ts → figure-properties.ts} +25 -25
  20. package/client/modeller/{figure-v3-recipe-catalog.ts → figure-recipe-catalog.ts} +10 -10
  21. package/client/modeller/{figure-v3-verdict.ts → figure-verdict.ts} +24 -24
  22. package/client/modeller/gate-findings.ts +2 -2
  23. package/client/modeller/{v3-gizmo.ts → gizmo.ts} +11 -11
  24. package/client/modeller/{v3-joint-drag.ts → joint-drag.ts} +11 -11
  25. package/client/modeller/{v3-joint-fan.ts → joint-fan.ts} +13 -13
  26. package/client/modeller/{v3-links.ts → links.ts} +59 -59
  27. package/client/modeller/{v3-live.ts → live.ts} +9 -9
  28. package/client/modeller/{v3-maturity.ts → maturity.ts} +65 -65
  29. package/client/modeller/modeller-route.ts +1 -1
  30. package/client/modeller/{v3-occupancy.ts → occupancy.ts} +6 -6
  31. package/client/modeller/{v3-palette.ts → palette.ts} +3 -3
  32. package/client/modeller/{v3-preview-model.ts → preview-model.ts} +8 -8
  33. package/client/modeller/{v3-product-session.ts → product-session.ts} +25 -25
  34. package/client/modeller/{v3-recipe-source.ts → recipe-source.ts} +2 -2
  35. package/client/modeller/{v3-recipes.ts → recipes.ts} +9 -9
  36. package/client/modeller/{v3-renderer.ts → renderer.ts} +16 -16
  37. package/client/modeller/{v3-stage-model.ts → stage-model.ts} +15 -15
  38. package/client/modeller/{v3-thumbnail.ts → thumbnail.ts} +8 -8
  39. package/client/pages/figure-list-page.ts +4 -4
  40. package/client/pages/{figure-v3-modeller-page.ts → figure-modeller-page.ts} +37 -37
  41. package/client/route.ts +1 -5
  42. package/dist-client/figure-assistant.js +3 -3
  43. package/dist-client/figure-assistant.js.map +1 -1
  44. package/dist-client/graphql/store.d.ts +3 -0
  45. package/dist-client/graphql/{v3-store.js → store.js} +6 -6
  46. package/dist-client/graphql/store.js.map +1 -0
  47. package/dist-client/modeller/{v3-ai-proposal.d.ts → ai-proposal.d.ts} +7 -7
  48. package/dist-client/modeller/{v3-ai-proposal.js → ai-proposal.js} +1 -1
  49. package/dist-client/modeller/ai-proposal.js.map +1 -0
  50. package/dist-client/modeller/{v3-align.d.ts → align.d.ts} +8 -8
  51. package/dist-client/modeller/{v3-align.js → align.js} +6 -6
  52. package/dist-client/modeller/align.js.map +1 -0
  53. package/dist-client/modeller/{v3-canvas.d.ts → canvas.d.ts} +7 -7
  54. package/dist-client/modeller/{v3-canvas.js → canvas.js} +20 -20
  55. package/dist-client/modeller/canvas.js.map +1 -0
  56. package/dist-client/modeller/{v3-clips.d.ts → clips.d.ts} +4 -4
  57. package/dist-client/modeller/{v3-clips.js → clips.js} +1 -1
  58. package/dist-client/modeller/clips.js.map +1 -0
  59. package/dist-client/modeller/{v3-controls.d.ts → controls.d.ts} +2 -2
  60. package/dist-client/modeller/{v3-controls.js → controls.js} +1 -1
  61. package/dist-client/modeller/controls.js.map +1 -0
  62. package/dist-client/modeller/{v3-editor.d.ts → editor.d.ts} +19 -19
  63. package/dist-client/modeller/{v3-editor.js → editor.js} +103 -103
  64. package/dist-client/modeller/editor.js.map +1 -0
  65. package/dist-client/modeller/{v3-fields.js → fields.js} +1 -1
  66. package/dist-client/modeller/fields.js.map +1 -0
  67. package/dist-client/modeller/{figure-v3-capability.d.ts → figure-capability-panel.d.ts} +4 -4
  68. package/dist-client/modeller/{figure-v3-capability.js → figure-capability-panel.js} +12 -12
  69. package/dist-client/modeller/figure-capability-panel.js.map +1 -0
  70. package/dist-client/modeller/{figure-v3-clips.d.ts → figure-clips.d.ts} +4 -4
  71. package/dist-client/modeller/{figure-v3-clips.js → figure-clips.js} +16 -16
  72. package/dist-client/modeller/figure-clips.js.map +1 -0
  73. package/dist-client/modeller/{figure-v3-controls.d.ts → figure-controls.d.ts} +5 -5
  74. package/dist-client/modeller/{figure-v3-controls.js → figure-controls.js} +16 -16
  75. package/dist-client/modeller/figure-controls.js.map +1 -0
  76. package/dist-client/modeller/{v3-figure-facts.d.ts → figure-facts.d.ts} +5 -5
  77. package/dist-client/modeller/{v3-figure-facts.js → figure-facts.js} +5 -5
  78. package/dist-client/modeller/figure-facts.js.map +1 -0
  79. package/dist-client/modeller/{figure-v3-first-save.d.ts → figure-first-save.d.ts} +1 -1
  80. package/dist-client/modeller/{figure-v3-first-save.js → figure-first-save.js} +11 -11
  81. package/dist-client/modeller/figure-first-save.js.map +1 -0
  82. package/dist-client/modeller/figure-history-panel.d.ts +1 -1
  83. package/dist-client/modeller/figure-history-panel.js.map +1 -1
  84. package/dist-client/modeller/{figure-v3-links.d.ts → figure-links.d.ts} +5 -5
  85. package/dist-client/modeller/{figure-v3-links.js → figure-links.js} +24 -24
  86. package/dist-client/modeller/figure-links.js.map +1 -0
  87. package/dist-client/modeller/{figure-v3-material.d.ts → figure-material-panel.d.ts} +9 -9
  88. package/dist-client/modeller/{figure-v3-material.js → figure-material-panel.js} +19 -19
  89. package/dist-client/modeller/figure-material-panel.js.map +1 -0
  90. package/dist-client/modeller/{figure-v3-parts.d.ts → figure-parts.d.ts} +12 -12
  91. package/dist-client/modeller/{figure-v3-parts.js → figure-parts.js} +14 -14
  92. package/dist-client/modeller/figure-parts.js.map +1 -0
  93. package/dist-client/modeller/{figure-v3-preview.d.ts → figure-preview.d.ts} +4 -4
  94. package/dist-client/modeller/{figure-v3-preview.js → figure-preview.js} +21 -21
  95. package/dist-client/modeller/figure-preview.js.map +1 -0
  96. package/dist-client/modeller/{figure-v3-properties.d.ts → figure-properties.d.ts} +8 -8
  97. package/dist-client/modeller/{figure-v3-properties.js → figure-properties.js} +25 -25
  98. package/dist-client/modeller/figure-properties.js.map +1 -0
  99. package/dist-client/modeller/{figure-v3-recipe-catalog.d.ts → figure-recipe-catalog.d.ts} +4 -4
  100. package/dist-client/modeller/{figure-v3-recipe-catalog.js → figure-recipe-catalog.js} +21 -21
  101. package/dist-client/modeller/figure-recipe-catalog.js.map +1 -0
  102. package/dist-client/modeller/{figure-v3-verdict.d.ts → figure-verdict.d.ts} +2 -2
  103. package/dist-client/modeller/{figure-v3-verdict.js → figure-verdict.js} +26 -26
  104. package/dist-client/modeller/figure-verdict.js.map +1 -0
  105. package/dist-client/modeller/{v3-first-save.js → first-save.js} +1 -1
  106. package/dist-client/modeller/first-save.js.map +1 -0
  107. package/dist-client/modeller/gate-findings.d.ts +2 -2
  108. package/dist-client/modeller/gate-findings.js +2 -2
  109. package/dist-client/modeller/gate-findings.js.map +1 -1
  110. package/dist-client/modeller/{v3-gizmo.d.ts → gizmo.d.ts} +5 -5
  111. package/dist-client/modeller/{v3-gizmo.js → gizmo.js} +3 -3
  112. package/dist-client/modeller/gizmo.js.map +1 -0
  113. package/dist-client/modeller/{v3-help.js → help.js} +1 -1
  114. package/dist-client/modeller/help.js.map +1 -0
  115. package/dist-client/modeller/joint-drag.d.ts +19 -0
  116. package/dist-client/modeller/{v3-joint-drag.js → joint-drag.js} +4 -4
  117. package/dist-client/modeller/joint-drag.js.map +1 -0
  118. package/dist-client/modeller/{v3-joint-fan.d.ts → joint-fan.d.ts} +3 -3
  119. package/dist-client/modeller/{v3-joint-fan.js → joint-fan.js} +6 -6
  120. package/dist-client/modeller/joint-fan.js.map +1 -0
  121. package/dist-client/modeller/{v3-keys.js → keys.js} +1 -1
  122. package/dist-client/modeller/keys.js.map +1 -0
  123. package/dist-client/modeller/{v3-links.d.ts → links.d.ts} +48 -48
  124. package/dist-client/modeller/{v3-links.js → links.js} +15 -15
  125. package/dist-client/modeller/links.js.map +1 -0
  126. package/dist-client/modeller/{v3-live.d.ts → live.d.ts} +6 -6
  127. package/dist-client/modeller/{v3-live.js → live.js} +5 -5
  128. package/dist-client/modeller/live.js.map +1 -0
  129. package/dist-client/modeller/{v3-maturity.d.ts → maturity.d.ts} +26 -26
  130. package/dist-client/modeller/{v3-maturity.js → maturity.js} +28 -28
  131. package/dist-client/modeller/maturity.js.map +1 -0
  132. package/dist-client/modeller/modeller-route.d.ts +1 -1
  133. package/dist-client/modeller/modeller-route.js +1 -1
  134. package/dist-client/modeller/modeller-route.js.map +1 -1
  135. package/dist-client/modeller/{v3-occupancy.d.ts → occupancy.d.ts} +4 -4
  136. package/dist-client/modeller/{v3-occupancy.js → occupancy.js} +6 -6
  137. package/dist-client/modeller/occupancy.js.map +1 -0
  138. package/dist-client/modeller/palette.d.ts +7 -0
  139. package/dist-client/modeller/{v3-palette.js → palette.js} +1 -1
  140. package/dist-client/modeller/palette.js.map +1 -0
  141. package/dist-client/modeller/{v3-preview-model.d.ts → preview-model.d.ts} +3 -3
  142. package/dist-client/modeller/{v3-preview-model.js → preview-model.js} +6 -6
  143. package/dist-client/modeller/preview-model.js.map +1 -0
  144. package/dist-client/modeller/{v3-product-session.d.ts → product-session.d.ts} +56 -56
  145. package/dist-client/modeller/{v3-product-session.js → product-session.js} +7 -7
  146. package/dist-client/modeller/product-session.js.map +1 -0
  147. package/dist-client/modeller/{v3-recipe-source.d.ts → recipe-source.d.ts} +2 -2
  148. package/dist-client/modeller/{v3-recipe-source.js → recipe-source.js} +3 -3
  149. package/dist-client/modeller/recipe-source.js.map +1 -0
  150. package/dist-client/modeller/{v3-recipes.d.ts → recipes.d.ts} +7 -7
  151. package/dist-client/modeller/{v3-recipes.js → recipes.js} +4 -4
  152. package/dist-client/modeller/recipes.js.map +1 -0
  153. package/dist-client/modeller/{v3-refusals.js → refusals.js} +1 -1
  154. package/dist-client/modeller/refusals.js.map +1 -0
  155. package/dist-client/modeller/{v3-renderer.d.ts → renderer.d.ts} +6 -6
  156. package/dist-client/modeller/{v3-renderer.js → renderer.js} +13 -13
  157. package/dist-client/modeller/renderer.js.map +1 -0
  158. package/dist-client/modeller/{v3-stage-model.d.ts → stage-model.d.ts} +7 -7
  159. package/dist-client/modeller/{v3-stage-model.js → stage-model.js} +5 -5
  160. package/dist-client/modeller/stage-model.js.map +1 -0
  161. package/dist-client/modeller/thumbnail.d.ts +3 -0
  162. package/dist-client/modeller/{v3-thumbnail.js → thumbnail.js} +6 -6
  163. package/dist-client/modeller/thumbnail.js.map +1 -0
  164. package/dist-client/pages/figure-list-page.d.ts +1 -1
  165. package/dist-client/pages/figure-list-page.js +4 -4
  166. package/dist-client/pages/figure-list-page.js.map +1 -1
  167. package/dist-client/pages/{figure-v3-modeller-page.d.ts → figure-modeller-page.d.ts} +10 -10
  168. package/dist-client/pages/{figure-v3-modeller-page.js → figure-modeller-page.js} +42 -42
  169. package/dist-client/pages/figure-modeller-page.js.map +1 -0
  170. package/dist-client/route.d.ts +1 -1
  171. package/dist-client/route.js +1 -5
  172. package/dist-client/route.js.map +1 -1
  173. package/dist-client/tsconfig.tsbuildinfo +1 -1
  174. package/docs/product-cutover.md +25 -0
  175. package/package.json +5 -5
  176. package/test/{v3-ai-proposal.test.ts → ai-proposal.test.ts} +6 -6
  177. package/test/{v3-align.test.ts → align.test.ts} +8 -8
  178. package/test/browser/modeller-page.js +30 -30
  179. package/test/browser/modeller.check.mjs +14 -14
  180. package/test/browser/serve.mjs +1 -1
  181. package/test/browser/thumbnail-page.js +6 -6
  182. package/test/{v3-clips.test.ts → clips.test.ts} +18 -18
  183. package/test/{v3-controls.test.ts → controls.test.ts} +15 -15
  184. package/test/{v3-fields.test.ts → fields.test.ts} +13 -13
  185. package/test/figure-assistant-surface.test.ts +3 -3
  186. package/test/{v3-first-save.test.ts → first-save.test.ts} +10 -10
  187. package/test/fixtures/joint-column.json +2 -2
  188. package/test/fixtures/joint-roller.json +2 -2
  189. package/test/fixtures/robot-arm-6dof.json +2 -2
  190. package/test/{v3-gizmo.test.ts → gizmo.test.ts} +33 -33
  191. package/test/{v3-joint-drag.test.ts → joint-drag.test.ts} +17 -17
  192. package/test/{v3-joint-fan.test.ts → joint-fan.test.ts} +18 -18
  193. package/test/joints.ts +6 -6
  194. package/test/{v3-keys.test.ts → keys.test.ts} +2 -2
  195. package/test/{v3-layout.test.ts → layout.test.ts} +8 -8
  196. package/test/{v3-links.test.ts → links.test.ts} +201 -201
  197. package/test/{v3-live.test.ts → live.test.ts} +18 -18
  198. package/test/{v3-material.test.ts → material.test.ts} +12 -12
  199. package/test/{v3-maturity.test.ts → maturity.test.ts} +74 -74
  200. package/test/modeller-route.test.ts +5 -6
  201. package/test/{v3-palette-icons.test.ts → palette-icons.test.ts} +1 -1
  202. package/test/{v3-parts-wiring.test.ts → parts-wiring.test.ts} +5 -5
  203. package/test/{v3-preview.test.ts → preview.test.ts} +12 -12
  204. package/test/{v3-product-session.test.ts → product-session.test.ts} +17 -17
  205. package/test/{v3-product-write.test.ts → product-write.test.ts} +20 -20
  206. package/test/{v3-properties.test.ts → properties.test.ts} +24 -24
  207. package/test/{v3-recipes.test.ts → recipes.test.ts} +9 -9
  208. package/test/{v3-refusals.test.ts → refusals.test.ts} +43 -43
  209. package/test/{v3-release-panel.test.ts → release-panel.test.ts} +21 -21
  210. package/test/renderer.test.ts +24 -0
  211. package/test/resolve-ts-siblings.mjs +1 -1
  212. package/test/{v3-scene-canvas.test.ts → scene-canvas.test.ts} +6 -6
  213. package/test/{v3-stage-model.test.ts → stage-model.test.ts} +5 -5
  214. package/test/{v3-theme.test.ts → theme.test.ts} +4 -4
  215. package/test/{v3-thumbnail.test.ts → thumbnail.test.ts} +4 -4
  216. package/test/{v3-verdict.test.ts → verdict.test.ts} +17 -17
  217. package/test/{v3-view.test.ts → view.test.ts} +2 -2
  218. package/things-factory.config.js +2 -3
  219. package/translations/en.json +2 -2
  220. package/translations/ja.json +2 -2
  221. package/translations/ko.json +2 -2
  222. package/translations/ms.json +2 -2
  223. package/translations/zh.json +2 -2
  224. package/dist-client/graphql/v3-store.d.ts +0 -3
  225. package/dist-client/graphql/v3-store.js.map +0 -1
  226. package/dist-client/modeller/figure-v3-capability.js.map +0 -1
  227. package/dist-client/modeller/figure-v3-clips.js.map +0 -1
  228. package/dist-client/modeller/figure-v3-controls.js.map +0 -1
  229. package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
  230. package/dist-client/modeller/figure-v3-links.js.map +0 -1
  231. package/dist-client/modeller/figure-v3-material.js.map +0 -1
  232. package/dist-client/modeller/figure-v3-parts.js.map +0 -1
  233. package/dist-client/modeller/figure-v3-preview.js.map +0 -1
  234. package/dist-client/modeller/figure-v3-properties.js.map +0 -1
  235. package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
  236. package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
  237. package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
  238. package/dist-client/modeller/v3-align.js.map +0 -1
  239. package/dist-client/modeller/v3-canvas.js.map +0 -1
  240. package/dist-client/modeller/v3-clips.js.map +0 -1
  241. package/dist-client/modeller/v3-controls.js.map +0 -1
  242. package/dist-client/modeller/v3-editor.js.map +0 -1
  243. package/dist-client/modeller/v3-fields.js.map +0 -1
  244. package/dist-client/modeller/v3-figure-facts.js.map +0 -1
  245. package/dist-client/modeller/v3-first-save.js.map +0 -1
  246. package/dist-client/modeller/v3-gizmo.js.map +0 -1
  247. package/dist-client/modeller/v3-help.js.map +0 -1
  248. package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
  249. package/dist-client/modeller/v3-joint-drag.js.map +0 -1
  250. package/dist-client/modeller/v3-joint-fan.js.map +0 -1
  251. package/dist-client/modeller/v3-keys.js.map +0 -1
  252. package/dist-client/modeller/v3-links.js.map +0 -1
  253. package/dist-client/modeller/v3-live.js.map +0 -1
  254. package/dist-client/modeller/v3-maturity.js.map +0 -1
  255. package/dist-client/modeller/v3-occupancy.js.map +0 -1
  256. package/dist-client/modeller/v3-palette.d.ts +0 -7
  257. package/dist-client/modeller/v3-palette.js.map +0 -1
  258. package/dist-client/modeller/v3-preview-model.js.map +0 -1
  259. package/dist-client/modeller/v3-product-session.js.map +0 -1
  260. package/dist-client/modeller/v3-recipe-source.js.map +0 -1
  261. package/dist-client/modeller/v3-recipes.js.map +0 -1
  262. package/dist-client/modeller/v3-refusals.js.map +0 -1
  263. package/dist-client/modeller/v3-renderer.js.map +0 -1
  264. package/dist-client/modeller/v3-stage-model.js.map +0 -1
  265. package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
  266. package/dist-client/modeller/v3-thumbnail.js.map +0 -1
  267. package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
  268. package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
  269. package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
  270. package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
  271. package/docs/v3-product-cutover.md +0 -25
  272. package/test/v3-renderer.test.ts +0 -24
  273. /package/client/modeller/{v3-fields.ts → fields.ts} +0 -0
  274. /package/client/modeller/{v3-first-save.ts → first-save.ts} +0 -0
  275. /package/client/modeller/{v3-help.ts → help.ts} +0 -0
  276. /package/client/modeller/{v3-keys.ts → keys.ts} +0 -0
  277. /package/client/modeller/{v3-refusals.ts → refusals.ts} +0 -0
  278. /package/dist-client/modeller/{v3-fields.d.ts → fields.d.ts} +0 -0
  279. /package/dist-client/modeller/{v3-first-save.d.ts → first-save.d.ts} +0 -0
  280. /package/dist-client/modeller/{v3-help.d.ts → help.d.ts} +0 -0
  281. /package/dist-client/modeller/{v3-keys.d.ts → keys.d.ts} +0 -0
  282. /package/dist-client/modeller/{v3-refusals.d.ts → refusals.d.ts} +0 -0
@@ -1,14 +1,14 @@
1
- import type { V3Asset, V3PartEdit } from '@hatiolab/figure-model';
2
- import { type V3RenderPart } from './v3-renderer.js';
1
+ import type { FigureAsset, FigurePartEdit } from '@hatiolab/figure-model';
2
+ import { type FigureRenderPart } from './renderer.js';
3
3
  export interface LiveValues {
4
4
  /** Input values in hand, design or state, by input id. */
5
5
  values: Record<string, number>;
6
6
  /** A part edit in hand, not yet committed. */
7
- edit?: V3PartEdit;
7
+ edit?: FigurePartEdit;
8
8
  }
9
9
  export declare const NOTHING_LIVE: LiveValues;
10
10
  /** Known inputs with a number, split by what they are. An id the figure does not declare is dropped. */
11
- export declare function liveOverridesOf(asset: V3Asset, values: Record<string, number>): {
11
+ export declare function liveOverridesOf(asset: FigureAsset, values: Record<string, number>): {
12
12
  design: Record<string, number>;
13
13
  state: Record<string, number>;
14
14
  };
@@ -20,7 +20,7 @@ export declare function isLive(live: LiveValues): boolean;
20
20
  * refuses): the canvas keeps the figure as it stands until the release, and the release reports why through the same
21
21
  * refusal every committed edit gets. A preview never invents a figure the commit would not make.
22
22
  */
23
- export declare function livePartsOf(asset: V3Asset, live: LiveValues): V3RenderPart[] | null;
23
+ export declare function livePartsOf(asset: FigureAsset, live: LiveValues): FigureRenderPart[] | null;
24
24
  /**
25
25
  * How much one pixel of a label drag moves a value: a degree for an angle, a hundredth for a ratio, and for a length a
26
26
  * step that suits its size -- a millimetre under 100, ten over 1,000 -- so a 12 m wall and a 5 mm pin both scrub at a
@@ -34,4 +34,4 @@ export declare function scrubbed(start: number, pixels: number, step: number): n
34
34
  * author has already set with the other controls, and the design values. Drawing over the asset's saved defaults put
35
35
  * every other joint back to its saved angle while one slider moved (user, 2026-09-24: the arm jumped on release).
36
36
  */
37
- export declare function liveOverSession(asset: V3Asset, current: Record<string, number>, live: LiveValues): V3RenderPart[] | null;
37
+ export declare function liveOverSession(asset: FigureAsset, current: Record<string, number>, live: LiveValues): FigureRenderPart[] | null;
@@ -1,5 +1,5 @@
1
- import { compileV3Asset, editV3Part } from '@hatiolab/figure-model';
2
- import { drawableV3Parts } from './v3-renderer.js';
1
+ import { compileFigureAsset, editFigurePart } from '@hatiolab/figure-model';
2
+ import { drawableFigureParts } from './renderer.js';
3
3
  export const NOTHING_LIVE = { values: {} };
4
4
  /** Known inputs with a number, split by what they are. An id the figure does not declare is dropped. */
5
5
  export function liveOverridesOf(asset, values) {
@@ -31,10 +31,10 @@ export function livePartsOf(asset, live) {
31
31
  return null;
32
32
  const { design, state } = liveOverridesOf(asset, live.values);
33
33
  try {
34
- let next = live.edit ? editV3Part(asset, live.edit) : asset;
34
+ let next = live.edit ? editFigurePart(asset, live.edit) : asset;
35
35
  if (Object.keys(design).length)
36
36
  next = { ...next, designInputs: { ...next.designInputs, ...design } };
37
- return drawableV3Parts(compileV3Asset(next).evaluate(state).geometry);
37
+ return drawableFigureParts(compileFigureAsset(next).evaluate(state).geometry);
38
38
  }
39
39
  catch {
40
40
  return null;
@@ -65,4 +65,4 @@ export function liveOverSession(asset, current, live) {
65
65
  return null;
66
66
  return livePartsOf(asset, { ...live, values: { ...current, ...live.values } });
67
67
  }
68
- //# sourceMappingURL=v3-live.js.map
68
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../client/modeller/live.ts"],"names":[],"mappings":"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","sourcesContent":["import { compileFigureAsset, editFigurePart } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigurePartEdit } from '@hatiolab/figure-model'\n\nimport { drawableFigureParts, type FigureRenderPart } from './renderer.js'\n\n/*\n * The figure while a value is in hand: evaluated with the values being typed or dragged, drawn at once and written\n * nowhere. The panels committed on release only, so the canvas stood still while a number was typed, a spinner held,\n * a label scrubbed, a slider or the glow dragged (user, 2026-09-24: \"make the editor move naturally while the value\n * changes\"). The value in hand shows here; the release is the one step of the history.\n *\n * What is in hand is either input values -- a design value (a size, a position) or a pose -- or one part edit (the\n * glow of a material). A design value is a change of the figure's design, so it is shown by evaluating a copy with\n * that value; a pose is a state override, as the preview gives it.\n */\n\nexport interface LiveValues {\n /** Input values in hand, design or state, by input id. */\n values: Record<string, number>\n /** A part edit in hand, not yet committed. */\n edit?: FigurePartEdit\n}\n\nexport const NOTHING_LIVE: LiveValues = { values: {} }\n\n/** Known inputs with a number, split by what they are. An id the figure does not declare is dropped. */\nexport function liveOverridesOf(asset: FigureAsset, values: Record<string, number>): { design: Record<string, number>; state: Record<string, number> } {\n const roles = new Map(asset.document.model.inputs.map(i => [i.id, i.role]))\n const design: Record<string, number> = {},\n state: Record<string, number> = {}\n for (const [id, value] of Object.entries(values)) {\n if (!Number.isFinite(value)) continue\n const role = roles.get(id)\n if (role === 'state') state[id] = value\n else if (role !== undefined) design[id] = value\n }\n return { design, state }\n}\n\nexport function isLive(live: LiveValues): boolean {\n return !!live.edit || Object.keys(live.values).length > 0\n}\n\n/**\n * The bodies to draw with what is in hand, or null when nothing is -- then the evaluation as it stands is drawn.\n *\n * Also null when the figure cannot take the value in hand (a size of 0 on the way to typing 0.5, a glow the material\n * refuses): the canvas keeps the figure as it stands until the release, and the release reports why through the same\n * refusal every committed edit gets. A preview never invents a figure the commit would not make.\n */\nexport function livePartsOf(asset: FigureAsset, live: LiveValues): FigureRenderPart[] | null {\n if (!isLive(live)) return null\n const { design, state } = liveOverridesOf(asset, live.values)\n try {\n let next = live.edit ? editFigurePart(asset, live.edit) : asset\n if (Object.keys(design).length) next = { ...next, designInputs: { ...next.designInputs, ...design } }\n return drawableFigureParts(compileFigureAsset(next).evaluate(state).geometry)\n } catch {\n return null\n }\n}\n\n/**\n * How much one pixel of a label drag moves a value: a degree for an angle, a hundredth for a ratio, and for a length a\n * step that suits its size -- a millimetre under 100, ten over 1,000 -- so a 12 m wall and a 5 mm pin both scrub at a\n * usable pace. Shift makes it ten times finer.\n */\nexport function scrubStep(unit: string, value: number, fine = false): number {\n const base =\n unit === 'deg' ? 1 : unit === 'ratio' ? 0.01 : Math.max(1, Math.pow(10, Math.floor(Math.log10(Math.max(1, Math.abs(value)))) - 2))\n return fine ? base / 10 : base\n}\n\n/** A scrubbed value on the step's grid, so a drag does not leave 1203.0000000002 behind. */\nexport function scrubbed(start: number, pixels: number, step: number): number {\n const value = start + pixels * step\n const digits = Math.max(0, -Math.floor(Math.log10(step)))\n return Number(value.toFixed(digits))\n}\n\n/**\n * The bodies to draw while a value is in hand, over every input as the session holds it now (`current`): the pose the\n * author has already set with the other controls, and the design values. Drawing over the asset's saved defaults put\n * every other joint back to its saved angle while one slider moved (user, 2026-09-24: the arm jumped on release).\n */\nexport function liveOverSession(asset: FigureAsset, current: Record<string, number>, live: LiveValues): FigureRenderPart[] | null {\n if (!isLive(live)) return null\n return livePartsOf(asset, { ...live, values: { ...current, ...live.values } })\n}\n\n"]}
@@ -1,12 +1,12 @@
1
- import { V3_BUDGET_KEYS, V3_GRADE_SCALE, v3GradeOf } from '@hatiolab/figure-model';
2
- import type { V3Asset, V3AssetGeometry, V3BudgetKey, V3BudgetUse, V3Cost, V3Geometry, V3Score } from '@hatiolab/figure-model';
1
+ import { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE, figureGradeOf } from '@hatiolab/figure-model';
2
+ import type { FigureAsset, FigureAssetGeometry, FigureBudgetKey, FigureBudgetUse, FigureCost, FigureGeometry, FigureScore } from '@hatiolab/figure-model';
3
3
  import type { FigureCapacity } from './scene-budget.js';
4
- export { V3_BUDGET_KEYS, V3_GRADE_SCALE as GRADE_SCALE, v3GradeOf as gradeOf };
5
- export type { V3BudgetKey, V3BudgetUse, V3Score };
6
- export type V3AxisKey = 'scale' | 'consistency' | 'reuse' | 'detail' | 'reactive' | 'readable';
4
+ export { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE as GRADE_SCALE, figureGradeOf as gradeOf };
5
+ export type { FigureBudgetKey, FigureBudgetUse, FigureScore };
6
+ export type FigureAxisKey = 'scale' | 'consistency' | 'reuse' | 'detail' | 'reactive' | 'readable';
7
7
  /** One maturity axis. */
8
- export interface V3MaturityAxis {
9
- key: V3AxisKey;
8
+ export interface FigureMaturityAxis {
9
+ key: FigureAxisKey;
10
10
  /** 0–1. Absent when the axis cannot be measured. */
11
11
  ratio?: number;
12
12
  reading?: string;
@@ -17,7 +17,7 @@ export interface V3MaturityAxis {
17
17
  blocked?: string;
18
18
  }
19
19
  /** Instances on one screen, and what each series costs at that count. */
20
- export interface V3CurvePoint {
20
+ export interface FigureCurvePoint {
21
21
  instances: number;
22
22
  triangles: number;
23
23
  drawCalls: number;
@@ -25,10 +25,10 @@ export interface V3CurvePoint {
25
25
  geometries: number;
26
26
  materials: number;
27
27
  }
28
- export interface V3Report {
29
- cost: V3Cost;
28
+ export interface FigureReport {
29
+ cost: FigureCost;
30
30
  capacity: FigureCapacity;
31
- score: V3Score;
31
+ score: FigureScore;
32
32
  /** Distinct shapes and materials among the drawn bodies — the 「그리는 비용」 rows. */
33
33
  distinctShapes: number;
34
34
  distinctMaterials: number;
@@ -37,8 +37,8 @@ export interface V3Report {
37
37
  parts: number;
38
38
  saved: number;
39
39
  };
40
- axes: V3MaturityAxis[];
41
- curve: V3CurvePoint[];
40
+ axes: FigureMaturityAxis[];
41
+ curve: FigureCurvePoint[];
42
42
  }
43
43
  /** The board target for the scale axis: 500 assets on one drawing (design document §4.15). */
44
44
  export declare const BOARD_ASSETS = 500;
@@ -46,28 +46,28 @@ export declare const BOARD_ASSETS = 500;
46
46
  * The report for one asset, or nothing when no body is drawn — then there is nothing to measure, and the screen
47
47
  * says so rather than drawing zeros.
48
48
  *
49
- * Evaluated at the asset's own design and state defaults, as `v3CostOf` is.
49
+ * Evaluated at the asset's own design and state defaults, as `figureCostOf` is.
50
50
  */
51
- export declare function v3ReportOf(asset: V3Asset): V3Report | undefined;
51
+ export declare function figureReportOf(asset: FigureAsset): FigureReport | undefined;
52
52
  /**
53
- * The key things-scene shares a body's geometry by (`figure-v3-geometry.ts` `keyOf`): provider, dimensions to a
53
+ * The key things-scene shares a body's geometry by (`figure-geometry.ts` `keyOf`): provider, dimensions to a
54
54
  * micrometre, segments (12 when unset), and a polygon's corners.
55
55
  */
56
- export declare function shapeKeyOf(body: V3AssetGeometry | V3Geometry): string;
56
+ export declare function shapeKeyOf(body: FigureAssetGeometry | FigureGeometry): string;
57
57
  /**
58
- * The key things-scene shares a material by (`figure-v3-rig.ts` `materialFor`), within one asset: token, preset,
58
+ * The key things-scene shares a material by (`figure-rig.ts` `materialFor`), within one asset: token, preset,
59
59
  * transparency, and the light when it is on. The colour follows from the token, so it is not a second key.
60
60
  */
61
- export declare function materialKeyOf(body: V3AssetGeometry): string;
61
+ export declare function materialKeyOf(body: FigureAssetGeometry): string;
62
62
  /** 1 · 2 · 5 per decade: even steps on a log axis. */
63
63
  export declare function decadeSteps(from: number, to: number): number[];
64
- export type V3CurveSeries = 'triangles' | 'drawCalls' | 'geometries' | 'materials';
64
+ export type FigureCurveSeries = 'triangles' | 'drawCalls' | 'geometries' | 'materials';
65
65
  /**
66
66
  * The four lines: two that grow with the instance count and two that stay flat — the flat ones are what the
67
67
  * instances share. Materials are dashed and drawn last, so a line under them still shows where the two meet.
68
68
  */
69
69
  export declare const CURVE_SERIES: readonly {
70
- key: V3CurveSeries;
70
+ key: FigureCurveSeries;
71
71
  flat: boolean;
72
72
  dashed?: boolean;
73
73
  }[];
@@ -82,7 +82,7 @@ export declare const CURVE_SIZE: {
82
82
  readonly left: 62;
83
83
  };
84
84
  };
85
- export interface V3CurveLayout {
85
+ export interface FigureCurveLayout {
86
86
  xTicks: {
87
87
  x: number;
88
88
  label: string;
@@ -92,7 +92,7 @@ export interface V3CurveLayout {
92
92
  label: string;
93
93
  }[];
94
94
  lines: {
95
- key: V3CurveSeries;
95
+ key: FigureCurveSeries;
96
96
  d: string;
97
97
  flat: boolean;
98
98
  dashed: boolean;
@@ -104,9 +104,9 @@ export interface V3CurveLayout {
104
104
  /** 1, 10, 100 … written short. */
105
105
  export declare function shortNumber(v: number): string;
106
106
  /** Where the chart puts each line and tick. Both axes are logarithmic. */
107
- export declare function curveLayout(points: V3CurvePoint[]): V3CurveLayout | undefined;
107
+ export declare function curveLayout(points: FigureCurvePoint[]): FigureCurveLayout | undefined;
108
108
  /** What the parts list shows under its title: the cost, how many fit, the grade and what decides it. */
109
- export interface V3BudgetLine {
109
+ export interface FigureBudgetLine {
110
110
  triangles: number;
111
111
  groups: number;
112
112
  instances: number;
@@ -117,4 +117,4 @@ export interface V3BudgetLine {
117
117
  limit: number;
118
118
  };
119
119
  }
120
- export declare function budgetOf(report: V3Report | undefined): V3BudgetLine | undefined;
120
+ export declare function budgetOf(report: FigureReport | undefined): FigureBudgetLine | undefined;
@@ -1,56 +1,56 @@
1
- import { compileV3Asset, compileV3Document, LIMITS, SEGMENT_PRESETS, V3_BUDGET_KEYS, V3_GRADE_SCALE, v3CostOf, v3GradeOf, v3MaterialKeyOf, v3ScoreOf, v3WorldBoxesOf, v3WritersOf } from '@hatiolab/figure-model';
1
+ import { compileFigureAsset, compileFigureDocument, LIMITS, SEGMENT_PRESETS, FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE, figureCostOf, figureGradeOf, figureMaterialKeyOf, figureScoreOf, figureWorldBoxesOf, figureWritersOf } from '@hatiolab/figure-model';
2
2
  import { capacityFrom } from './scene-budget.js';
3
3
  /*
4
4
  * The modeller's maturity report, read off the evaluated asset (user, 2026-09-24: the tab showed a count and nothing
5
5
  * else — 「왜 이렇게 너프되었는지」):
6
6
  *
7
- * grade A–D and its scale figure-model's `v3ScoreOf`: one screen's target shared per instance (groups,
7
+ * grade A–D and its scale figure-model's `figureScoreOf`: one screen's target shared per instance (groups,
8
8
  * triangles) and the declared rule limits (independent, transparent)
9
- * radar · axes six axes; reactive is not measured, and detail has no V3 field
9
+ * radar · axes six axes; reactive is not measured, and detail has no field
10
10
  * drawing cost triangles, distinct shapes, distinct materials
11
11
  * trend what grows with the instance count and what the instances share
12
12
  *
13
13
  * Kept apart from the element so it can be tested without a browser.
14
14
  *
15
- * ## What the V3 renderer shares, which is what the numbers count
15
+ * ## What the renderer shares, which is what the numbers count
16
16
  *
17
- * things-scene draws one mesh per drawn body (`figure-v3-rig.ts`) — no merging by material — so a body is
18
- * a draw call. It shares geometry by provider, dimensions, segments and profile (`figure-v3-geometry.ts`, `keyOf`)
17
+ * things-scene draws one mesh per drawn body (`figure-rig.ts`) — no merging by material — so a body is
18
+ * a draw call. It shares geometry by provider, dimensions, segments and profile (`figure-geometry.ts`, `keyOf`)
19
19
  * and materials by token, preset, transparency and light (`materialFor`). The keys below are those keys; a
20
20
  * distinct-shape count that used another key would describe a renderer that does not exist.
21
21
  *
22
- * ## Budgets V3 does not have
22
+ * ## Budgets does not have
23
23
  *
24
24
  * Two budgets are not measured here, and are not shown as zero:
25
- * - off-palette surfaces: the V3 material has no surface field, so there is nothing to count;
26
- * - part count by detail level: V3 does not carry the detail level (chief architect, 2026-09-24, ADR-0087).
25
+ * - off-palette surfaces: the material has no surface field, so there is nothing to count;
26
+ * - part count by detail level: does not carry the detail level (chief architect, 2026-09-24, ADR-0087).
27
27
  */
28
28
  /*
29
- The grade, its budgets and its bounds are figure-model's (`v3ScoreOf`), so the catalogue grades a figure as this tab
29
+ The grade, its budgets and its bounds are figure-model's (`figureScoreOf`), so the catalogue grades a figure as this tab
30
30
  does. The grade is the headroom against one screen's target (`LIMITS.screenInstances`), not a draw-call limit.
31
31
  */
32
- export { V3_BUDGET_KEYS, V3_GRADE_SCALE as GRADE_SCALE, v3GradeOf as gradeOf };
32
+ export { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE as GRADE_SCALE, figureGradeOf as gradeOf };
33
33
  /** The board target for the scale axis: 500 assets on one drawing (design document §4.15). */
34
34
  export const BOARD_ASSETS = 500;
35
35
  /**
36
36
  * The report for one asset, or nothing when no body is drawn — then there is nothing to measure, and the screen
37
37
  * says so rather than drawing zeros.
38
38
  *
39
- * Evaluated at the asset's own design and state defaults, as `v3CostOf` is.
39
+ * Evaluated at the asset's own design and state defaults, as `figureCostOf` is.
40
40
  */
41
- export function v3ReportOf(asset) {
42
- const cost = v3CostOf(asset);
41
+ export function figureReportOf(asset) {
42
+ const cost = figureCostOf(asset);
43
43
  const capacity = capacityFrom(cost.groups, cost.triangles);
44
44
  if (!capacity)
45
45
  return undefined;
46
- const drawn = compileV3Asset(asset)
46
+ const drawn = compileFigureAsset(asset)
47
47
  .evaluate()
48
48
  .geometry.filter(body => body.visible !== false);
49
- const plan = compileV3Document(asset.document);
50
- const writers = v3WritersOf(asset);
49
+ const plan = compileFigureDocument(asset.document);
50
+ const writers = figureWritersOf(asset);
51
51
  const shapes = new Set(drawn.map(shapeKeyOf));
52
52
  const materials = new Set(drawn.map(materialKeyOf));
53
- const score = v3ScoreOf(asset);
53
+ const score = figureScoreOf(asset);
54
54
  const reuse = { distinct: shapes.size, parts: drawn.length, saved: drawn.length - shapes.size };
55
55
  const axes = [
56
56
  {
@@ -90,7 +90,7 @@ export function v3ReportOf(asset) {
90
90
  };
91
91
  }
92
92
  /**
93
- * The key things-scene shares a body's geometry by (`figure-v3-geometry.ts` `keyOf`): provider, dimensions to a
93
+ * The key things-scene shares a body's geometry by (`figure-geometry.ts` `keyOf`): provider, dimensions to a
94
94
  * micrometre, segments (12 when unset), and a polygon's corners.
95
95
  */
96
96
  export function shapeKeyOf(body) {
@@ -110,17 +110,17 @@ export function shapeKeyOf(body) {
110
110
  return `${shape.provider}|${dims}|s${segments}${profile}`;
111
111
  }
112
112
  /**
113
- * The key things-scene shares a material by (`figure-v3-rig.ts` `materialFor`), within one asset: token, preset,
113
+ * The key things-scene shares a material by (`figure-rig.ts` `materialFor`), within one asset: token, preset,
114
114
  * transparency, and the light when it is on. The colour follows from the token, so it is not a second key.
115
115
  */
116
116
  export function materialKeyOf(body) {
117
- return v3MaterialKeyOf(body);
117
+ return figureMaterialKeyOf(body);
118
118
  }
119
119
  /**
120
120
  * Does it look like one set — baselines 3 and 4, three checks.
121
121
  *
122
- * Two of them hold by construction in V3: the material has no surface field, so there is no texture, and the
123
- * format refuses a segment count outside the presets (`compileV3Asset`, `QUALITY`). They are still counted, so
122
+ * Two of them hold by construction: the material has no surface field, so there is no texture, and the
123
+ * format refuses a segment count outside the presets (`compileFigureAsset`, `QUALITY`). They are still counted, so
124
124
  * the ratio stays one fault in three.
125
125
  */
126
126
  function consistency(asset, distinctMaterials) {
@@ -134,7 +134,7 @@ function consistency(asset, distinctMaterials) {
134
134
  because: 'figure.text.maturity-consistency-because'
135
135
  };
136
136
  }
137
- /** Seen from above, these do not fill their footprint box, by V3 provider name. */
137
+ /** Seen from above, these do not fill their footprint box, by provider name. */
138
138
  const ROUND_FOOTPRINT = ['cylinder', 'ellipticCylinder', 'frustum', 'sphere'];
139
139
  /**
140
140
  * Can it be told apart from above — baseline 1.
@@ -143,15 +143,15 @@ const ROUND_FOOTPRINT = ['cylinder', 'ellipticCylinder', 'frustum', 'sphere'];
143
143
  * finer segment count does not raise it: H = −Σ p·log p over each material's share of the footprint plus the
144
144
  * background, divided by log(`LIMITS.distinctMaterials` + 1), the most this measure can reach.
145
145
  *
146
- * The footprint is the base box: the space the asset declares when it declares one (ADR-0044's box is V3's
146
+ * The footprint is the base box: the space the asset declares when it declares one (ADR-0044's box is the model's
147
147
  * occupancy), otherwise the drawn bodies' own extent. Bodies are their axis-aligned world boxes
148
- * (`v3WorldBoxesOf`, the gate's reading); the higher one covers the lower.
148
+ * (`figureWorldBoxesOf`, the gate's reading); the higher one covers the lower.
149
149
  */
150
150
  function readable(asset, plan, drawn, writers) {
151
151
  const placed = drawn
152
152
  .filter(body => 'pose' in body)
153
153
  // One placed, drawn body gives exactly one box; boxes are taken one by one to keep each with its material.
154
- .map(body => ({ body, box: v3WorldBoxesOf([body], writers)[0] }));
154
+ .map(body => ({ body, box: figureWorldBoxesOf([body], writers)[0] }));
155
155
  if (placed.length === 0)
156
156
  return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' };
157
157
  let frame;
@@ -310,4 +310,4 @@ export function budgetOf(report) {
310
310
  tightest: { key: tightest.key, used: tightest.used, limit: Math.floor(tightest.limit) }
311
311
  };
312
312
  }
313
- //# sourceMappingURL=v3-maturity.js.map
313
+ //# sourceMappingURL=maturity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maturity.js","sourceRoot":"","sources":["../../client/modeller/maturity.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compileFigureAsset,\n compileFigureDocument,\n LIMITS,\n SEGMENT_PRESETS,\n FIGURE_BUDGET_KEYS,\n FIGURE_GRADE_SCALE,\n figureCostOf,\n figureGradeOf,\n figureMaterialKeyOf,\n figureScoreOf,\n figureWorldBoxesOf,\n figureWritersOf\n} from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureAssetGeometry, FigureBudgetKey, FigureBudgetUse, FigureCost, FigureGeometry, FigureScore } from '@hatiolab/figure-model'\n\nimport { capacityFrom } from './scene-budget.js'\nimport type { FigureCapacity } from './scene-budget.js'\n\n/*\n * The modeller's maturity report, read off the evaluated asset (user, 2026-09-24: the tab showed a count and nothing\n * else — 「왜 이렇게 너프되었는지」):\n *\n * grade A–D and its scale figure-model's `figureScoreOf`: one screen's target shared per instance (groups,\n * triangles) and the declared rule limits (independent, transparent)\n * radar · axes six axes; reactive is not measured, and detail has no field\n * drawing cost triangles, distinct shapes, distinct materials\n * trend what grows with the instance count and what the instances share\n *\n * Kept apart from the element so it can be tested without a browser.\n *\n * ## What the renderer shares, which is what the numbers count\n *\n * things-scene draws one mesh per drawn body (`figure-rig.ts`) — no merging by material — so a body is\n * a draw call. It shares geometry by provider, dimensions, segments and profile (`figure-geometry.ts`, `keyOf`)\n * and materials by token, preset, transparency and light (`materialFor`). The keys below are those keys; a\n * distinct-shape count that used another key would describe a renderer that does not exist.\n *\n * ## Budgets does not have\n *\n * Two budgets are not measured here, and are not shown as zero:\n * - off-palette surfaces: the material has no surface field, so there is nothing to count;\n * - part count by detail level: does not carry the detail level (chief architect, 2026-09-24, ADR-0087).\n */\n\n/*\n The grade, its budgets and its bounds are figure-model's (`figureScoreOf`), so the catalogue grades a figure as this tab\n does. The grade is the headroom against one screen's target (`LIMITS.screenInstances`), not a draw-call limit.\n*/\nexport { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE as GRADE_SCALE, figureGradeOf as gradeOf }\nexport type { FigureBudgetKey, FigureBudgetUse, FigureScore }\n\nexport type FigureAxisKey = 'scale' | 'consistency' | 'reuse' | 'detail' | 'reactive' | 'readable'\n\n/** One maturity axis. */\nexport interface FigureMaturityAxis {\n key: FigureAxisKey\n /** 0–1. Absent when the axis cannot be measured. */\n ratio?: number\n reading?: string\n /** A reading that is words, not a number. */\n readingKey?: string\n because?: string\n /** Why the axis is not measured. When present there is no ratio — an unmeasured axis is not a zero. */\n blocked?: string\n}\n\n/** Instances on one screen, and what each series costs at that count. */\nexport interface FigureCurvePoint {\n instances: number\n triangles: number\n drawCalls: number\n /** Vertex buffers: one per distinct shape, shared by every instance of the same size. */\n geometries: number\n materials: number\n}\n\nexport interface FigureReport {\n cost: FigureCost\n capacity: FigureCapacity\n score: FigureScore\n /** Distinct shapes and materials among the drawn bodies — the 「그리는 비용」 rows. */\n distinctShapes: number\n distinctMaterials: number\n reuse: { distinct: number; parts: number; saved: number }\n axes: FigureMaturityAxis[]\n curve: FigureCurvePoint[]\n}\n\n/** The board target for the scale axis: 500 assets on one drawing (design document §4.15). */\nexport const BOARD_ASSETS = 500\n\n/**\n * The report for one asset, or nothing when no body is drawn — then there is nothing to measure, and the screen\n * says so rather than drawing zeros.\n *\n * Evaluated at the asset's own design and state defaults, as `figureCostOf` is.\n */\nexport function figureReportOf(asset: FigureAsset): FigureReport | undefined {\n const cost = figureCostOf(asset)\n const capacity = capacityFrom(cost.groups, cost.triangles)\n if (!capacity) return undefined\n\n const drawn = compileFigureAsset(asset)\n .evaluate()\n .geometry.filter(body => body.visible !== false)\n const plan = compileFigureDocument(asset.document)\n const writers = figureWritersOf(asset)\n\n const shapes = new Set(drawn.map(shapeKeyOf))\n const materials = new Set(drawn.map(materialKeyOf))\n\n const score = figureScoreOf(asset)!\n\n const reuse = { distinct: shapes.size, parts: drawn.length, saved: drawn.length - shapes.size }\n\n const axes: FigureMaturityAxis[] = [\n {\n key: 'scale',\n // The board target filled is 1; room beyond it is better spent on the other axes, so it does not count more.\n ratio: Math.min(1, capacity.instances / BOARD_ASSETS),\n reading: String(capacity.instances),\n because: 'figure.text.maturity-scale-because'\n },\n consistency(asset, materials.size),\n {\n key: 'reuse',\n // A low distinct-to-parts ratio is much reuse; turned over so that more is higher.\n ratio: reuse.parts === 0 ? 0 : 1 - reuse.distinct / reuse.parts,\n reading: String(reuse.saved),\n because: 'figure.text.maturity-reuse-because'\n },\n { key: 'detail', blocked: 'figure.text.maturity-blocked-no-detail-level' },\n { key: 'reactive', blocked: 'figure.text.maturity-blocked-no-binding' },\n readable(asset, plan, drawn, writers)\n ]\n\n return {\n cost,\n capacity,\n score,\n distinctShapes: shapes.size,\n distinctMaterials: materials.size,\n reuse,\n axes,\n curve: decadeSteps(1, 10000).map(instances => ({\n instances,\n triangles: cost.triangles * instances,\n drawCalls: cost.groups * instances,\n geometries: shapes.size,\n materials: materials.size\n }))\n }\n}\n\n/**\n * The key things-scene shares a body's geometry by (`figure-geometry.ts` `keyOf`): provider, dimensions to a\n * micrometre, segments (12 when unset), and a polygon's corners.\n */\nexport function shapeKeyOf(body: FigureAssetGeometry | FigureGeometry): string {\n if (!('shape' in body)) {\n // A scalar body has no mesh of its own; it is still one drawn body, told apart by what it declares.\n const dims = Object.keys(body.dimensions).sort().map(k => `${k}=${body.dimensions[k]}`).join(',')\n return `${body.provider}|${dims}`\n }\n const shape = body.shape\n const round = (v: number) => Math.round(v * 1e6) / 1e6\n const dims = Object.keys(shape.dimensions)\n .sort()\n .map(k => `${k}=${round(shape.dimensions[k]!)}`)\n .join(',')\n const profile = shape.profile ? '|' + shape.profile.map(p => `${round(p.x)}:${round(p.y)}`).join(';') : ''\n const segments = (body as { segments?: number }).segments ?? 12\n return `${shape.provider}|${dims}|s${segments}${profile}`\n}\n\n/**\n * The key things-scene shares a material by (`figure-rig.ts` `materialFor`), within one asset: token, preset,\n * transparency, and the light when it is on. The colour follows from the token, so it is not a second key.\n */\nexport function materialKeyOf(body: FigureAssetGeometry): string {\n return figureMaterialKeyOf(body)\n}\n\n/**\n * Does it look like one set — baselines 3 and 4, three checks.\n *\n * Two of them hold by construction: the material has no surface field, so there is no texture, and the\n * format refuses a segment count outside the presets (`compileFigureAsset`, `QUALITY`). They are still counted, so\n * the ratio stays one fault in three.\n */\nfunction consistency(asset: FigureAsset, distinctMaterials: number): FigureMaturityAxis {\n const textures = 0\n const offPreset = asset.appearance.filter(look => look.segments !== undefined && !SEGMENT_PRESETS.includes(look.segments)).length\n const faults = (textures > 0 ? 1 : 0) + (offPreset > 0 ? 1 : 0) + (distinctMaterials > LIMITS.distinctMaterials ? 1 : 0)\n return {\n key: 'consistency',\n ratio: (3 - faults) / 3,\n readingKey: faults === 0 ? 'figure.text.maturity-consistency-clean' : 'figure.text.maturity-consistency-faults',\n because: 'figure.text.maturity-consistency-because'\n }\n}\n\n/** Seen from above, these do not fill their footprint box, by provider name. */\nconst ROUND_FOOTPRINT: readonly string[] = ['cylinder', 'ellipticCylinder', 'frustum', 'sphere']\n\n/**\n * Can it be told apart from above — baseline 1.\n *\n * Viewpoint entropy (Vázquez et al.) over the top view, counted by colour region rather than by face so that a\n * finer segment count does not raise it: H = −Σ p·log p over each material's share of the footprint plus the\n * background, divided by log(`LIMITS.distinctMaterials` + 1), the most this measure can reach.\n *\n * The footprint is the base box: the space the asset declares when it declares one (ADR-0044's box is the model's\n * occupancy), otherwise the drawn bodies' own extent. Bodies are their axis-aligned world boxes\n * (`figureWorldBoxesOf`, the gate's reading); the higher one covers the lower.\n */\nfunction readable(\n asset: FigureAsset,\n plan: ReturnType<typeof compileFigureDocument>,\n drawn: FigureAssetGeometry[],\n writers: Map<string, string>\n): FigureMaturityAxis {\n const placed = drawn\n .filter(body => 'pose' in body)\n // One placed, drawn body gives exactly one box; boxes are taken one by one to keep each with its material.\n .map(body => ({ body, box: figureWorldBoxesOf([body], writers)[0]! }))\n if (placed.length === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n let frame: { x0: number; x1: number; z0: number; z1: number }\n if (asset.occupancy) {\n const values = plan.evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values\n const at = (ref: string) => values[ref] as number\n const b = asset.occupancy.bounds\n frame = { x0: at(b.x.min), x1: at(b.x.max), z0: at(b.z.min), z1: at(b.z.max) }\n } else {\n frame = { x0: Infinity, x1: -Infinity, z0: Infinity, z1: -Infinity }\n for (const { box } of placed) {\n frame.x0 = Math.min(frame.x0, box.centre.x - box.extent.x / 2)\n frame.x1 = Math.max(frame.x1, box.centre.x + box.extent.x / 2)\n frame.z0 = Math.min(frame.z0, box.centre.z - box.extent.z / 2)\n frame.z1 = Math.max(frame.z1, box.centre.z + box.extent.z / 2)\n }\n }\n\n const regions = topViewRegions(placed, frame)\n if (regions.total === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n const shares = [...regions.byMaterial.values(), regions.background].map(area => area / regions.footprint).filter(share => share > 0)\n const entropy = -shares.reduce((sum, p) => sum + p * Math.log(p), 0)\n const ceiling = Math.log(LIMITS.distinctMaterials + 1)\n return {\n key: 'readable',\n // Clamped both ways: one region alone gives −0, which is not a reading anyone should see.\n ratio: Math.max(0, Math.min(1, entropy / ceiling)),\n reading: String(regions.byMaterial.size),\n because: 'figure.text.maturity-readable-because'\n }\n}\n\n/** Which material shows from above, on a 64 × 64 grid over the footprint, over world boxes. */\nfunction topViewRegions(\n placed: { body: FigureAssetGeometry; box: ReturnType<typeof figureWorldBoxesOf>[number] }[],\n frame: { x0: number; x1: number; z0: number; z1: number }\n) {\n const GRID = 64\n const cells = new Array<string | null>(GRID * GRID).fill(null)\n const height = new Float64Array(GRID * GRID)\n const sx = GRID / Math.max(frame.x1 - frame.x0, 1e-6)\n const sz = GRID / Math.max(frame.z1 - frame.z0, 1e-6)\n\n for (const { body, box } of placed) {\n const top = box.centre.y + box.extent.y / 2\n const key = materialKeyOf(body)\n const x0 = Math.max(0, Math.floor((box.centre.x - box.extent.x / 2 - frame.x0) * sx))\n const x1 = Math.min(GRID, Math.ceil((box.centre.x + box.extent.x / 2 - frame.x0) * sx))\n const y0 = Math.max(0, Math.floor((box.centre.z - box.extent.z / 2 - frame.z0) * sz))\n const y1 = Math.min(GRID, Math.ceil((box.centre.z + box.extent.z / 2 - frame.z0) * sz))\n const round = 'shape' in body && ROUND_FOOTPRINT.includes(body.shape.provider)\n\n for (let y = y0; y < y1; y++) {\n for (let x = x0; x < x1; x++) {\n // A round body does not fill its box; the corners are cut.\n if (round) {\n const cx = (x + 0.5 - (x0 + x1) / 2) / ((x1 - x0) / 2 || 1)\n const cy = (y + 0.5 - (y0 + y1) / 2) / ((y1 - y0) / 2 || 1)\n if (cx * cx + cy * cy > 1) continue\n }\n const i = y * GRID + x\n if (cells[i] === null || top > height[i]!) {\n cells[i] = key\n height[i] = top\n }\n }\n }\n }\n\n const byMaterial = new Map<string, number>()\n let covered = 0\n for (const key of cells) {\n if (key === null) continue\n covered++\n byMaterial.set(key, (byMaterial.get(key) ?? 0) + 1)\n }\n return { byMaterial, total: covered, background: GRID * GRID - covered, footprint: GRID * GRID }\n}\n\n/** 1 · 2 · 5 per decade: even steps on a log axis. */\nexport function decadeSteps(from: number, to: number): number[] {\n const out: number[] = []\n for (let decade = 1; decade <= to; decade *= 10) {\n for (const m of [1, 2, 5]) {\n const v = decade * m\n if (v >= from && v <= to) out.push(v)\n }\n }\n if (out.length === 0 || out[out.length - 1] !== to) out.push(to)\n return [...new Set(out)].sort((a, b) => a - b)\n}\n\n// ─── The trend chart ─────────────────────────────────────────────────────────\n\nexport type FigureCurveSeries = 'triangles' | 'drawCalls' | 'geometries' | 'materials'\n\n/**\n * The four lines: two that grow with the instance count and two that stay flat — the flat ones are what the\n * instances share. Materials are dashed and drawn last, so a line under them still shows where the two meet.\n */\nexport const CURVE_SERIES: readonly { key: FigureCurveSeries; flat: boolean; dashed?: boolean }[] = [\n { key: 'triangles', flat: false },\n { key: 'drawCalls', flat: false },\n { key: 'geometries', flat: true },\n { key: 'materials', flat: true, dashed: true }\n]\n\n/** The chart's size. The chart is shown at this size in a sheet; shrunk into the side, its words are unreadable. */\nexport const CURVE_SIZE = { width: 680, height: 380, pad: { top: 52, right: 208, bottom: 44, left: 62 } } as const\n\nexport interface FigureCurveLayout {\n xTicks: { x: number; label: string }[]\n yTicks: { y: number; label: string }[]\n lines: { key: FigureCurveSeries; d: string; flat: boolean; dashed: boolean; last: number }[]\n /** The value the flat lines share when they lie on one another, so the screen can say why one line is missing. */\n overlap?: number\n}\n\nconst log10 = (v: number) => Math.log(Math.max(v, 1)) / Math.LN10\n\n/** 1, 10, 100 … written short. */\nexport function shortNumber(v: number): string {\n if (v >= 1_000_000) return `${v / 1_000_000}M`\n if (v >= 1_000) return `${v / 1_000}k`\n return String(v)\n}\n\n/** Where the chart puts each line and tick. Both axes are logarithmic. */\nexport function curveLayout(points: FigureCurvePoint[]): FigureCurveLayout | undefined {\n if (points.length === 0) return undefined\n const { width, height, pad } = CURVE_SIZE\n const minX = points[0]!.instances\n const maxX = points[points.length - 1]!.instances\n let maxY = 1\n for (const p of points) for (const s of CURVE_SERIES) maxY = Math.max(maxY, p[s.key])\n\n const plotW = width - pad.left - pad.right\n const plotH = height - pad.top - pad.bottom\n const spanX = Math.max(log10(maxX) - log10(minX), 1e-9)\n const spanY = Math.max(log10(maxY), 1e-9)\n const px = (v: number) => pad.left + ((log10(v) - log10(minX)) / spanX) * plotW\n const py = (v: number) => pad.top + plotH - (log10(v) / spanY) * plotH\n\n const yTicks: FigureCurveLayout['yTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxY * 1.001; e++) yTicks.push({ y: py(Math.pow(10, e)), label: shortNumber(Math.pow(10, e)) })\n const xTicks: FigureCurveLayout['xTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxX * 1.001; e++) {\n const v = Math.pow(10, e)\n if (v >= minX) xTicks.push({ x: px(v), label: shortNumber(v) })\n }\n\n const last = points[points.length - 1]!\n const lines = CURVE_SERIES.map(s => ({\n key: s.key,\n d: points.map((p, i) => `${i === 0 ? 'M' : 'L'}${px(p.instances).toFixed(1)},${py(p[s.key]).toFixed(1)}`).join(' '),\n flat: s.flat,\n dashed: !!s.dashed,\n last: last[s.key]\n }))\n const flat = new Set(CURVE_SERIES.filter(s => s.flat).map(s => last[s.key]))\n return { xTicks, yTicks, lines, overlap: flat.size === 1 ? [...flat][0] : undefined }\n}\n\n/** What the parts list shows under its title: the cost, how many fit, the grade and what decides it. */\nexport interface FigureBudgetLine {\n triangles: number\n groups: number\n instances: number\n grade: string\n tightest: { key: string; used: number; limit: number }\n}\n\nexport function budgetOf(report: FigureReport | undefined): FigureBudgetLine | undefined {\n if (!report) return undefined\n const { tightest } = report.score\n return {\n triangles: report.cost.triangles,\n groups: report.cost.groups,\n instances: report.capacity.instances,\n grade: report.score.grade,\n tightest: { key: tightest.key, used: tightest.used, limit: Math.floor(tightest.limit) }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-v3-modeller`
2
+ * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-modeller`
3
3
  * stays as an alias so a link written under that name still lands.
4
4
  */
5
5
  export declare const MODELLER = "figure-modeller";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-v3-modeller`
2
+ * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-modeller`
3
3
  * stays as an alias so a link written under that name still lands.
4
4
  */
5
5
  export const MODELLER = 'figure-modeller';
@@ -1 +1 @@
1
- {"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC","sourcesContent":["/**\n * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-v3-modeller`\n * stays as an alias so a link written under that name still lands.\n */\nexport const MODELLER = 'figure-modeller'\n\nexport function modellerPathOf(figure?: { id?: string }): string {\n return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER\n}\n"]}
1
+ {"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC","sourcesContent":["/**\n * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-modeller`\n * stays as an alias so a link written under that name still lands.\n */\nexport const MODELLER = 'figure-modeller'\n\nexport function modellerPathOf(figure?: { id?: string }): string {\n return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER\n}\n"]}
@@ -1,8 +1,8 @@
1
- import { type V3AuthoringAction } from '@hatiolab/figure-model';
1
+ import { type FigureAuthoringAction } from '@hatiolab/figure-model';
2
2
  /**
3
- * 「부품에 맞추기」의 V3 짝 — 공간을 지금 부품에서 다시 선언하는 한 걸음.
3
+ * 「부품에 맞추기」의 짝 — 공간을 지금 부품에서 다시 선언하는 한 걸음.
4
4
  *
5
- * figure-model 은 이것을 둘로 나눠 두었다: 제안(`proposeV3Occupancy`)은 무엇이 선언될지를 보여 주고, 확인
5
+ * figure-model 은 이것을 둘로 나눠 두었다: 제안(`proposeFigureOccupancy`)은 무엇이 선언될지를 보여 주고, 확인
6
6
  * (`declare-occupancy`)은 그 제안이 읽은 모양 그대로일 때만 받는다. 저작자가 누른 단추가 그 확인이다. 제안과 확인
7
7
  * 사이에 모델이 바뀌면 figure-model 이 `OCCUPANCY_STALE` 로 거절하므로, 여기서는 누른 순간의 원본으로 둘을 한
8
8
  * 번에 만든다.
@@ -13,6 +13,6 @@ import { type V3AuthoringAction } from '@hatiolab/figure-model';
13
13
  */
14
14
  export declare function occupancyFromParts(source: string,
15
15
  /** A different face to place it by — the properties tab's choice. Absent keeps the declared one. */
16
- placement?: 'floor' | 'ceiling' | 'center' | 'wall'): Extract<V3AuthoringAction, {
16
+ placement?: 'floor' | 'ceiling' | 'center' | 'wall'): Extract<FigureAuthoringAction, {
17
17
  kind: 'declare-occupancy';
18
18
  }>;
@@ -1,8 +1,8 @@
1
- import { parseV3Asset, proposeV3Occupancy } from '@hatiolab/figure-model';
1
+ import { parseFigureAsset, proposeFigureOccupancy } from '@hatiolab/figure-model';
2
2
  /**
3
- * 「부품에 맞추기」의 V3 짝 — 공간을 지금 부품에서 다시 선언하는 한 걸음.
3
+ * 「부품에 맞추기」의 짝 — 공간을 지금 부품에서 다시 선언하는 한 걸음.
4
4
  *
5
- * figure-model 은 이것을 둘로 나눠 두었다: 제안(`proposeV3Occupancy`)은 무엇이 선언될지를 보여 주고, 확인
5
+ * figure-model 은 이것을 둘로 나눠 두었다: 제안(`proposeFigureOccupancy`)은 무엇이 선언될지를 보여 주고, 확인
6
6
  * (`declare-occupancy`)은 그 제안이 읽은 모양 그대로일 때만 받는다. 저작자가 누른 단추가 그 확인이다. 제안과 확인
7
7
  * 사이에 모델이 바뀌면 figure-model 이 `OCCUPANCY_STALE` 로 거절하므로, 여기서는 누른 순간의 원본으로 둘을 한
8
8
  * 번에 만든다.
@@ -14,11 +14,11 @@ import { parseV3Asset, proposeV3Occupancy } from '@hatiolab/figure-model';
14
14
  export function occupancyFromParts(source,
15
15
  /** A different face to place it by — the properties tab's choice. Absent keeps the declared one. */
16
16
  placement) {
17
- const asset = parseV3Asset(source);
17
+ const asset = parseFigureAsset(source);
18
18
  return {
19
19
  kind: 'declare-occupancy',
20
- proposal: proposeV3Occupancy(asset, { over: 'range' }),
20
+ proposal: proposeFigureOccupancy(asset, { over: 'range' }),
21
21
  placement: placement ?? asset.occupancy?.placement ?? 'floor'
22
22
  };
23
23
  }
24
- //# sourceMappingURL=v3-occupancy.js.map
24
+ //# sourceMappingURL=occupancy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"occupancy.js","sourceRoot":"","sources":["../../client/modeller/occupancy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAA8B,MAAM,wBAAwB,CAAA;AAE7G;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAc;AACd,oGAAoG;AACpG,SAAmD;IAEnD,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACtC,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,sBAAsB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC1D,SAAS,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,OAAO;KAC9D,CAAA;AACH,CAAC","sourcesContent":["import { parseFigureAsset, proposeFigureOccupancy, type FigureAuthoringAction } from '@hatiolab/figure-model'\n\n/**\n * 「부품에 맞추기」의 짝 — 공간을 지금 부품에서 다시 선언하는 한 걸음.\n *\n * figure-model 은 이것을 둘로 나눠 두었다: 제안(`proposeFigureOccupancy`)은 무엇이 선언될지를 보여 주고, 확인\n * (`declare-occupancy`)은 그 제안이 읽은 모양 그대로일 때만 받는다. 저작자가 누른 단추가 그 확인이다. 제안과 확인\n * 사이에 모델이 바뀌면 figure-model 이 `OCCUPANCY_STALE` 로 거절하므로, 여기서는 누른 순간의 원본으로 둘을 한\n * 번에 만든다.\n *\n * 범위는 움직임 전체다(`over: 'range'`). 쉬는 자세만 담으면 움직이는 부품이 선언한 공간을 넘어 발행 판정이 다시\n * 막는다. 배치 기준은 이미 선언된 것을 지키고, 처음 선언하는 도형은 바닥에 선다고 둔다 — 새로 만든 도형의\n * 모델러 기본이 바닥이다.\n */\nexport function occupancyFromParts(\n source: string,\n /** A different face to place it by — the properties tab's choice. Absent keeps the declared one. */\n placement?: 'floor' | 'ceiling' | 'center' | 'wall'\n): Extract<FigureAuthoringAction, { kind: 'declare-occupancy' }> {\n const asset = parseFigureAsset(source)\n return {\n kind: 'declare-occupancy',\n proposal: proposeFigureOccupancy(asset, { over: 'range' }),\n placement: placement ?? asset.occupancy?.placement ?? 'floor'\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { FigurePrimitiveCreation } from '@hatiolab/figure-model';
2
+ import type { FigurePaletteKind } from './figure-parts.js';
3
+ /**
4
+ * What a palette button makes: the part at a starting size a person then changes. Standing on the floor (its lowest
5
+ * point at y 0) where the provider's frame is centred; a portal's frame already rises from its bottom.
6
+ */
7
+ export declare function paletteRecipe(kind: FigurePaletteKind, id: string): FigurePrimitiveCreation;
@@ -43,4 +43,4 @@ export function paletteRecipe(kind, id) {
43
43
  };
44
44
  }
45
45
  }
46
- //# sourceMappingURL=v3-palette.js.map
46
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../../client/modeller/palette.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FigurePrimitiveCreation } from '@hatiolab/figure-model'\n\nimport type { FigurePaletteKind } from './figure-parts.js'\n\n/**\n * What a palette button makes: the part at a starting size a person then changes. Standing on the floor (its lowest\n * point at y 0) where the provider's frame is centred; a portal's frame already rises from its bottom.\n */\nexport function paletteRecipe(kind: FigurePaletteKind, id: string): FigurePrimitiveCreation {\n const standing = (height: number) => ({ id, position: { x: 0, y: height / 2, z: 0 } })\n switch (kind) {\n case 'box':\n return { ...standing(100), kind, dimensions: { width: 100, height: 100, depth: 100 } }\n case 'cylinder':\n return { ...standing(100), kind, dimensions: { radius: 50, length: 100 } }\n case 'rounded-box':\n return { ...standing(100), kind, dimensions: { width: 100, height: 100, depth: 100, round: 10 } }\n case 'sphere':\n return { ...standing(100), kind, dimensions: { radiusX: 50, radiusY: 50, radiusZ: 50 } }\n case 'frustum':\n return { ...standing(100), kind, dimensions: { radiusTop: 0, radiusBottom: 50, height: 100 } }\n case 'polygon':\n return {\n ...standing(100),\n kind,\n dimensions: { height: 100 },\n points: [\n { x: -50, z: -43 },\n { x: 50, z: -43 },\n { x: 0, z: 43 }\n ]\n }\n case 'plate':\n return { ...standing(10), kind: 'box', dimensions: { width: 600, height: 10, depth: 400 } }\n case 'wall':\n return { ...standing(2400), kind: 'box', dimensions: { width: 1000, height: 2400, depth: 100 } }\n case 'hollow-box':\n /* A tote at a tote's size: walls and floor that keep their thickness when it grows. */\n return { ...standing(300), kind: 'hollow-box', dimensions: { width: 600, height: 300, depth: 400, roundX: 20, roundZ: 20, wallX: 10, wallZ: 10, floor: 15 } }\n case 'portal':\n return {\n id,\n position: { x: 0, y: 0, z: 0 },\n kind: 'portal',\n /* A door frame at a door's size, as a wall is a wall's: its width, height, depth and the jambs' and head's thickness. */\n dimensions: { width: 1000, height: 2200, depth: 150, jamb: 100, head: 100 }\n }\n }\n}\n"]}
@@ -1,11 +1,11 @@
1
- import type { V3Asset } from '@hatiolab/figure-model';
1
+ import type { FigureAsset } from '@hatiolab/figure-model';
2
2
  export declare const PREVIEW_FACTOR = 2;
3
3
  export declare const PREVIEW_WAYS: readonly {
4
4
  name: string;
5
5
  axes: readonly ('x' | 'y' | 'z')[];
6
6
  }[];
7
7
  /** The size the figure was made at: its instance size when it declares one, else the room its bodies take. */
8
- export declare function authoredSizeOf(asset: V3Asset): {
8
+ export declare function authoredSizeOf(asset: FigureAsset): {
9
9
  x: number;
10
10
  y: number;
11
11
  z: number;
@@ -36,7 +36,7 @@ export declare function previewInstances(type: string, size: {
36
36
  * it is drawn as asked. A figure that follows its height only is drawn at its one width in the wider variants, and
37
37
  * the preview says so rather than drawing them as though they grew.
38
38
  */
39
- export declare function previewClampsOf(asset: V3Asset, size: {
39
+ export declare function previewClampsOf(asset: FigureAsset, size: {
40
40
  x: number;
41
41
  y: number;
42
42
  z: number;
@@ -1,5 +1,5 @@
1
- import { compileV3Asset, v3OccupiedBoxesOf, v3WritersOf, V3_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model';
2
- /* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-v3-preview.ts). */
1
+ import { compileFigureAsset, figureOccupiedBoxesOf, figureWritersOf, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model';
2
+ /* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-preview.ts). */
3
3
  export const PREVIEW_FACTOR = 2;
4
4
  export const PREVIEW_WAYS = [
5
5
  { name: 'base', axes: [] },
@@ -14,11 +14,11 @@ export const PREVIEW_WAYS = [
14
14
  /** The size the figure was made at: its instance size when it declares one, else the room its bodies take. */
15
15
  export function authoredSizeOf(asset) {
16
16
  const d = asset.designInputs;
17
- const declared = ['x', 'y', 'z'].map(axis => d[V3_INSTANCE_SIZE_INPUTS[axis]]);
17
+ const declared = ['x', 'y', 'z'].map(axis => d[FIGURE_INSTANCE_SIZE_INPUTS[axis]]);
18
18
  if (declared.every(v => typeof v === 'number' && v > 0))
19
19
  return { x: declared[0], y: declared[1], z: declared[2] };
20
20
  /* No declared size: the room its bodies take up, so the instance is placed at the size it draws. */
21
- const boxes = v3OccupiedBoxesOf(compileV3Asset(asset).evaluate().geometry, v3WritersOf(asset));
21
+ const boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset));
22
22
  const span = (axis) => boxes.length ? Math.max(...boxes.map(b => b.centre[axis] + b.extent[axis] / 2)) - Math.min(...boxes.map(b => b.centre[axis] - b.extent[axis] / 2)) : 0;
23
23
  return { x: Math.max(1, Math.round(span('x'))), y: Math.max(1, Math.round(span('y'))), z: Math.max(1, Math.round(span('z'))) };
24
24
  }
@@ -56,7 +56,7 @@ export function previewClampsOf(asset, size) {
56
56
  return Object.fromEntries(PREVIEW_WAYS.map(way => [
57
57
  way.name,
58
58
  ['x', 'y', 'z'].flatMap(axis => {
59
- const input = inputs.find(i => i.id === V3_INSTANCE_SIZE_INPUTS[axis]);
59
+ const input = inputs.find(i => i.id === FIGURE_INSTANCE_SIZE_INPUTS[axis]);
60
60
  if (!input)
61
61
  return [];
62
62
  const asked = Math.round(size[axis] * (way.axes.includes(axis) ? PREVIEW_FACTOR : 1));
@@ -65,4 +65,4 @@ export function previewClampsOf(asset, size) {
65
65
  })
66
66
  ]));
67
67
  }
68
- //# sourceMappingURL=v3-preview-model.js.map
68
+ //# sourceMappingURL=preview-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-model.js","sourceRoot":"","sources":["../../client/modeller/preview-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { compileFigureAsset, figureOccupiedBoxesOf, figureWritersOf, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model'\nimport type { FigureAsset } from '@hatiolab/figure-model'\n\n/* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-preview.ts). */\n\nexport const PREVIEW_FACTOR = 2\n\nexport const PREVIEW_WAYS: readonly { name: string; axes: readonly ('x' | 'y' | 'z')[] }[] = [\n { name: 'base', axes: [] },\n { name: 'x', axes: ['x'] },\n { name: 'y', axes: ['y'] },\n { name: 'z', axes: ['z'] },\n { name: 'x·y', axes: ['x', 'y'] },\n { name: 'x·z', axes: ['x', 'z'] },\n { name: 'y·z', axes: ['y', 'z'] },\n { name: 'x·y·z', axes: ['x', 'y', 'z'] }\n]\n\n/** The size the figure was made at: its instance size when it declares one, else the room its bodies take. */\nexport function authoredSizeOf(asset: FigureAsset): { x: number; y: number; z: number } {\n const d = asset.designInputs\n const declared = (['x', 'y', 'z'] as const).map(axis => d[FIGURE_INSTANCE_SIZE_INPUTS[axis]])\n if (declared.every(v => typeof v === 'number' && v > 0)) return { x: declared[0]!, y: declared[1]!, z: declared[2]! }\n /* No declared size: the room its bodies take up, so the instance is placed at the size it draws. */\n const boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset))\n const span = (axis: 'x' | 'y' | 'z') =>\n boxes.length ? Math.max(...boxes.map(b => b.centre[axis] + b.extent[axis] / 2)) - Math.min(...boxes.map(b => b.centre[axis] - b.extent[axis] / 2)) : 0\n return { x: Math.max(1, Math.round(span('x'))), y: Math.max(1, Math.round(span('y'))), z: Math.max(1, Math.round(span('z'))) }\n}\n\n/** The eight instances: where each stands on the board and how large, in the scene's words. */\nexport function previewInstances(type: string, size: { x: number; y: number; z: number }) {\n const COLUMNS = 4\n const cell = { x: size.x * PREVIEW_FACTOR * 1.25, z: size.z * PREVIEW_FACTOR * 1.25 }\n const components = PREVIEW_WAYS.map((way, at) => {\n const grow = (axis: 'x' | 'y' | 'z') => (way.axes.includes(axis) ? PREVIEW_FACTOR : 1)\n const width = Math.round(size.x * grow('x'))\n const height = Math.round(size.z * grow('z'))\n const column = at % COLUMNS\n const row = Math.floor(at / COLUMNS)\n return {\n type,\n id: `at-${way.name}`,\n left: Math.round(column * cell.x + (cell.x - width) / 2),\n top: Math.round(row * cell.z + (cell.z - height) / 2),\n width,\n height,\n /* Always written: without it the height is taken as the plan's mean and \"grow y only\" would not grow it. */\n depth: Math.round(size.y * grow('y'))\n }\n })\n return { components, board: { width: Math.round(cell.x * COLUMNS), height: Math.round(cell.z * Math.ceil(PREVIEW_WAYS.length / COLUMNS)) } }\n}\n\n\n/**\n * Where a variant asks a size the figure does not declare, the size it is drawn at instead -- as the board draws it\n * (things-scene clamps each axis to the declared range; chief architect's ruling 2026-09-25). Per variant, empty when\n * it is drawn as asked. A figure that follows its height only is drawn at its one width in the wider variants, and\n * the preview says so rather than drawing them as though they grew.\n */\nexport function previewClampsOf(asset: FigureAsset, size: { x: number; y: number; z: number }): Record<string, Array<{ axis: 'x' | 'y' | 'z'; asked: number; used: number }>> {\n const inputs = asset.document.model.inputs\n return Object.fromEntries(\n PREVIEW_WAYS.map(way => [\n way.name,\n (['x', 'y', 'z'] as const).flatMap(axis => {\n const input = inputs.find(i => i.id === FIGURE_INSTANCE_SIZE_INPUTS[axis])\n if (!input) return []\n const asked = Math.round(size[axis] * (way.axes.includes(axis) ? PREVIEW_FACTOR : 1))\n const used = Math.round(Math.min(Math.max(asked, input.min ?? -Infinity), input.max ?? Infinity))\n return used === asked ? [] : [{ axis, asked, used }]\n })\n ])\n )\n}\n"]}