@12ui/design 0.2.71 → 0.2.73

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 (680) hide show
  1. package/README.md +248 -55
  2. package/SKILL.md +28 -33
  3. package/dist/cli-arguments.d.ts.map +1 -1
  4. package/dist/cli-arguments.js +3 -0
  5. package/dist/cli-arguments.js.map +1 -1
  6. package/dist/cli-branch-command.d.ts.map +1 -1
  7. package/dist/cli-branch-command.js +4 -0
  8. package/dist/cli-branch-command.js.map +1 -1
  9. package/dist/cli-capabilities.d.ts +35 -1
  10. package/dist/cli-capabilities.d.ts.map +1 -1
  11. package/dist/cli-capabilities.js +36 -1
  12. package/dist/cli-capabilities.js.map +1 -1
  13. package/dist/cli-corpus-command.d.ts +5 -4
  14. package/dist/cli-corpus-command.d.ts.map +1 -1
  15. package/dist/cli-corpus-command.js +17 -26
  16. package/dist/cli-corpus-command.js.map +1 -1
  17. package/dist/cli-corpus-run.js +1 -1
  18. package/dist/cli-corpus-run.js.map +1 -1
  19. package/dist/cli-draft-command.js +1 -1
  20. package/dist/cli-draft-command.js.map +1 -1
  21. package/dist/cli-help/design.d.ts +26 -6
  22. package/dist/cli-help/design.d.ts.map +1 -1
  23. package/dist/cli-help/design.js +39 -7
  24. package/dist/cli-help/design.js.map +1 -1
  25. package/dist/cli-help/index.d.ts +206 -7
  26. package/dist/cli-help/index.d.ts.map +1 -1
  27. package/dist/cli-help/index.js +4 -0
  28. package/dist/cli-help/index.js.map +1 -1
  29. package/dist/cli-help/meta.d.ts +1 -1
  30. package/dist/cli-help/meta.d.ts.map +1 -1
  31. package/dist/cli-help/meta.js +2 -1
  32. package/dist/cli-help/meta.js.map +1 -1
  33. package/dist/cli-help/scene.d.ts +96 -0
  34. package/dist/cli-help/scene.d.ts.map +1 -0
  35. package/dist/cli-help/scene.js +162 -0
  36. package/dist/cli-help/scene.js.map +1 -0
  37. package/dist/cli-help/workflow.d.ts +90 -0
  38. package/dist/cli-help/workflow.d.ts.map +1 -0
  39. package/dist/cli-help/workflow.js +89 -0
  40. package/dist/cli-help/workflow.js.map +1 -0
  41. package/dist/cli-open-browser.d.ts +7 -0
  42. package/dist/cli-open-browser.d.ts.map +1 -0
  43. package/dist/cli-open-browser.js +25 -0
  44. package/dist/cli-open-browser.js.map +1 -0
  45. package/dist/cli-prototype-command.d.ts +3 -1
  46. package/dist/cli-prototype-command.d.ts.map +1 -1
  47. package/dist/cli-prototype-command.js +33 -7
  48. package/dist/cli-prototype-command.js.map +1 -1
  49. package/dist/cli-review-command.d.ts.map +1 -1
  50. package/dist/cli-review-command.js +1 -16
  51. package/dist/cli-review-command.js.map +1 -1
  52. package/dist/cli-run.d.ts.map +1 -1
  53. package/dist/cli-run.js +41 -3
  54. package/dist/cli-run.js.map +1 -1
  55. package/dist/cli-scene-command.d.ts +3 -0
  56. package/dist/cli-scene-command.d.ts.map +1 -0
  57. package/dist/cli-scene-command.js +292 -0
  58. package/dist/cli-scene-command.js.map +1 -0
  59. package/dist/cli-usage.d.ts +8 -0
  60. package/dist/cli-usage.d.ts.map +1 -1
  61. package/dist/cli-usage.js +65 -6
  62. package/dist/cli-usage.js.map +1 -1
  63. package/dist/cli-workflow-command.d.ts +8 -0
  64. package/dist/cli-workflow-command.d.ts.map +1 -0
  65. package/dist/cli-workflow-command.js +97 -0
  66. package/dist/cli-workflow-command.js.map +1 -0
  67. package/dist/cli-workspace-command.d.ts +25 -0
  68. package/dist/cli-workspace-command.d.ts.map +1 -0
  69. package/dist/cli-workspace-command.js +95 -0
  70. package/dist/cli-workspace-command.js.map +1 -0
  71. package/dist/config.d.ts +6 -0
  72. package/dist/config.d.ts.map +1 -1
  73. package/dist/config.js +12 -4
  74. package/dist/config.js.map +1 -1
  75. package/dist/corpus-access.d.ts +11 -0
  76. package/dist/corpus-access.d.ts.map +1 -0
  77. package/dist/corpus-access.js +18 -0
  78. package/dist/corpus-access.js.map +1 -0
  79. package/dist/corpus-client.d.ts +11 -11
  80. package/dist/corpus-client.d.ts.map +1 -1
  81. package/dist/corpus-client.js +17 -6
  82. package/dist/corpus-client.js.map +1 -1
  83. package/dist/corpus-inspiration-failure.d.ts +1 -1
  84. package/dist/corpus-inspiration-failure.js +2 -2
  85. package/dist/corpus-inspiration-failure.js.map +1 -1
  86. package/dist/corpus-reference-download-retry.d.ts.map +1 -1
  87. package/dist/corpus-reference-download-retry.js +11 -1
  88. package/dist/corpus-reference-download-retry.js.map +1 -1
  89. package/dist/corpus-request-error.d.ts +2 -0
  90. package/dist/corpus-request-error.d.ts.map +1 -1
  91. package/dist/corpus-request-error.js +2 -0
  92. package/dist/corpus-request-error.js.map +1 -1
  93. package/dist/corpus-retry-guidance.d.ts +5 -0
  94. package/dist/corpus-retry-guidance.d.ts.map +1 -0
  95. package/dist/corpus-retry-guidance.js +18 -0
  96. package/dist/corpus-retry-guidance.js.map +1 -0
  97. package/dist/improve-pricing-plan.d.ts.map +1 -1
  98. package/dist/improve-pricing-plan.js +2 -4
  99. package/dist/improve-pricing-plan.js.map +1 -1
  100. package/dist/index.d.ts +10 -1
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +10 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  105. package/dist/legacy-skill-catalog.js +52 -0
  106. package/dist/legacy-skill-catalog.js.map +1 -1
  107. package/dist/mcp-slate-command.d.ts +31 -0
  108. package/dist/mcp-slate-command.d.ts.map +1 -0
  109. package/dist/mcp-slate-command.js +118 -0
  110. package/dist/mcp-slate-command.js.map +1 -0
  111. package/dist/mcp-slate-image.d.ts +22 -0
  112. package/dist/mcp-slate-image.d.ts.map +1 -0
  113. package/dist/mcp-slate-image.js +28 -0
  114. package/dist/mcp-slate-image.js.map +1 -0
  115. package/dist/mcp-slate-latest.d.ts +13 -0
  116. package/dist/mcp-slate-latest.d.ts.map +1 -0
  117. package/dist/mcp-slate-latest.js +34 -0
  118. package/dist/mcp-slate-latest.js.map +1 -0
  119. package/dist/mcp-slate-names.d.ts +25 -0
  120. package/dist/mcp-slate-names.d.ts.map +1 -0
  121. package/dist/mcp-slate-names.js +49 -0
  122. package/dist/mcp-slate-names.js.map +1 -0
  123. package/dist/mcp-slate-resource.d.ts +5 -0
  124. package/dist/mcp-slate-resource.d.ts.map +1 -0
  125. package/dist/mcp-slate-resource.js +37 -0
  126. package/dist/mcp-slate-resource.js.map +1 -0
  127. package/dist/mcp-slate-run.d.ts +41 -0
  128. package/dist/mcp-slate-run.d.ts.map +1 -0
  129. package/dist/mcp-slate-run.js +88 -0
  130. package/dist/mcp-slate-run.js.map +1 -0
  131. package/dist/mcp-slate-tool-defs.d.ts +61 -0
  132. package/dist/mcp-slate-tool-defs.d.ts.map +1 -0
  133. package/dist/mcp-slate-tool-defs.js +247 -0
  134. package/dist/mcp-slate-tool-defs.js.map +1 -0
  135. package/dist/mcp-slate-tools.d.ts +8 -0
  136. package/dist/mcp-slate-tools.d.ts.map +1 -0
  137. package/dist/mcp-slate-tools.js +45 -0
  138. package/dist/mcp-slate-tools.js.map +1 -0
  139. package/dist/mcp-slate-ui-copy.d.ts +134 -0
  140. package/dist/mcp-slate-ui-copy.d.ts.map +1 -0
  141. package/dist/mcp-slate-ui-copy.js +136 -0
  142. package/dist/mcp-slate-ui-copy.js.map +1 -0
  143. package/dist/mcp-slate-ui-script-bridge.d.ts +18 -0
  144. package/dist/mcp-slate-ui-script-bridge.d.ts.map +1 -0
  145. package/dist/mcp-slate-ui-script-bridge.js +137 -0
  146. package/dist/mcp-slate-ui-script-bridge.js.map +1 -0
  147. package/dist/mcp-slate-ui-script-browser.d.ts +12 -0
  148. package/dist/mcp-slate-ui-script-browser.d.ts.map +1 -0
  149. package/dist/mcp-slate-ui-script-browser.js +19 -0
  150. package/dist/mcp-slate-ui-script-browser.js.map +1 -0
  151. package/dist/mcp-slate-ui-script-dialog.d.ts +20 -0
  152. package/dist/mcp-slate-ui-script-dialog.d.ts.map +1 -0
  153. package/dist/mcp-slate-ui-script-dialog.js +332 -0
  154. package/dist/mcp-slate-ui-script-dialog.js.map +1 -0
  155. package/dist/mcp-slate-ui-script-inline.d.ts +10 -0
  156. package/dist/mcp-slate-ui-script-inline.d.ts.map +1 -0
  157. package/dist/mcp-slate-ui-script-inline.js +221 -0
  158. package/dist/mcp-slate-ui-script-inline.js.map +1 -0
  159. package/dist/mcp-slate-ui-script-inspiration.d.ts +12 -0
  160. package/dist/mcp-slate-ui-script-inspiration.d.ts.map +1 -0
  161. package/dist/mcp-slate-ui-script-inspiration.js +216 -0
  162. package/dist/mcp-slate-ui-script-inspiration.js.map +1 -0
  163. package/dist/mcp-slate-ui-script-more.d.ts +30 -0
  164. package/dist/mcp-slate-ui-script-more.d.ts.map +1 -0
  165. package/dist/mcp-slate-ui-script-more.js +225 -0
  166. package/dist/mcp-slate-ui-script-more.js.map +1 -0
  167. package/dist/mcp-slate-ui-script-progress.d.ts +7 -0
  168. package/dist/mcp-slate-ui-script-progress.d.ts.map +1 -0
  169. package/dist/mcp-slate-ui-script-progress.js +9 -0
  170. package/dist/mcp-slate-ui-script-progress.js.map +1 -0
  171. package/dist/mcp-slate-ui-script-remote.d.ts +28 -0
  172. package/dist/mcp-slate-ui-script-remote.d.ts.map +1 -0
  173. package/dist/mcp-slate-ui-script-remote.js +147 -0
  174. package/dist/mcp-slate-ui-script-remote.js.map +1 -0
  175. package/dist/mcp-slate-ui-script-scribble.d.ts +19 -0
  176. package/dist/mcp-slate-ui-script-scribble.d.ts.map +1 -0
  177. package/dist/mcp-slate-ui-script-scribble.js +114 -0
  178. package/dist/mcp-slate-ui-script-scribble.js.map +1 -0
  179. package/dist/mcp-slate-ui-script-select.d.ts +16 -0
  180. package/dist/mcp-slate-ui-script-select.d.ts.map +1 -0
  181. package/dist/mcp-slate-ui-script-select.js +73 -0
  182. package/dist/mcp-slate-ui-script-select.js.map +1 -0
  183. package/dist/mcp-slate-ui-script-stage.d.ts +11 -0
  184. package/dist/mcp-slate-ui-script-stage.d.ts.map +1 -0
  185. package/dist/mcp-slate-ui-script-stage.js +181 -0
  186. package/dist/mcp-slate-ui-script-stage.js.map +1 -0
  187. package/dist/mcp-slate-ui-script-state.d.ts +13 -0
  188. package/dist/mcp-slate-ui-script-state.d.ts.map +1 -0
  189. package/dist/mcp-slate-ui-script-state.js +306 -0
  190. package/dist/mcp-slate-ui-script-state.js.map +1 -0
  191. package/dist/mcp-slate-ui-script-thumbtools.d.ts +23 -0
  192. package/dist/mcp-slate-ui-script-thumbtools.d.ts.map +1 -0
  193. package/dist/mcp-slate-ui-script-thumbtools.js +103 -0
  194. package/dist/mcp-slate-ui-script-thumbtools.js.map +1 -0
  195. package/dist/mcp-slate-ui-script.d.ts +28 -0
  196. package/dist/mcp-slate-ui-script.d.ts.map +1 -0
  197. package/dist/mcp-slate-ui-script.js +58 -0
  198. package/dist/mcp-slate-ui-script.js.map +1 -0
  199. package/dist/mcp-slate-ui-styles-dialog.d.ts +17 -0
  200. package/dist/mcp-slate-ui-styles-dialog.d.ts.map +1 -0
  201. package/dist/mcp-slate-ui-styles-dialog.js +73 -0
  202. package/dist/mcp-slate-ui-styles-dialog.js.map +1 -0
  203. package/dist/mcp-slate-ui-styles-stage.d.ts +12 -0
  204. package/dist/mcp-slate-ui-styles-stage.d.ts.map +1 -0
  205. package/dist/mcp-slate-ui-styles-stage.js +53 -0
  206. package/dist/mcp-slate-ui-styles-stage.js.map +1 -0
  207. package/dist/mcp-slate-ui-styles-thumbtools.d.ts +10 -0
  208. package/dist/mcp-slate-ui-styles-thumbtools.d.ts.map +1 -0
  209. package/dist/mcp-slate-ui-styles-thumbtools.js +25 -0
  210. package/dist/mcp-slate-ui-styles-thumbtools.js.map +1 -0
  211. package/dist/mcp-slate-ui-styles.d.ts +13 -0
  212. package/dist/mcp-slate-ui-styles.d.ts.map +1 -0
  213. package/dist/mcp-slate-ui-styles.js +117 -0
  214. package/dist/mcp-slate-ui-styles.js.map +1 -0
  215. package/dist/mcp-slate-ui.d.ts +16 -0
  216. package/dist/mcp-slate-ui.d.ts.map +1 -0
  217. package/dist/mcp-slate-ui.js +58 -0
  218. package/dist/mcp-slate-ui.js.map +1 -0
  219. package/dist/mcp-slate-workspace-tools.d.ts +15 -0
  220. package/dist/mcp-slate-workspace-tools.d.ts.map +1 -0
  221. package/dist/mcp-slate-workspace-tools.js +155 -0
  222. package/dist/mcp-slate-workspace-tools.js.map +1 -0
  223. package/dist/mcp-tool-definitions.d.ts.map +1 -1
  224. package/dist/mcp-tool-definitions.js +9 -7
  225. package/dist/mcp-tool-definitions.js.map +1 -1
  226. package/dist/mcp-tool-handler.d.ts +8 -2
  227. package/dist/mcp-tool-handler.d.ts.map +1 -1
  228. package/dist/mcp-tool-handler.js +34 -13
  229. package/dist/mcp-tool-handler.js.map +1 -1
  230. package/dist/mcp-workflow-tools.d.ts +6 -0
  231. package/dist/mcp-workflow-tools.d.ts.map +1 -0
  232. package/dist/mcp-workflow-tools.js +108 -0
  233. package/dist/mcp-workflow-tools.js.map +1 -0
  234. package/dist/prototype-browsers.d.ts +8 -2
  235. package/dist/prototype-browsers.d.ts.map +1 -1
  236. package/dist/prototype-browsers.js +8 -3
  237. package/dist/prototype-browsers.js.map +1 -1
  238. package/dist/prototype-label-client.d.ts +5 -0
  239. package/dist/prototype-label-client.d.ts.map +1 -1
  240. package/dist/prototype-label-client.js.map +1 -1
  241. package/dist/prototype-poststep.d.ts +2 -2
  242. package/dist/prototype-poststep.d.ts.map +1 -1
  243. package/dist/prototype-poststep.js +3 -0
  244. package/dist/prototype-poststep.js.map +1 -1
  245. package/dist/prototype-process.js +1 -1
  246. package/dist/prototype-process.js.map +1 -1
  247. package/dist/prototype-run-record.d.ts +6 -2
  248. package/dist/prototype-run-record.d.ts.map +1 -1
  249. package/dist/prototype-run-record.js +6 -0
  250. package/dist/prototype-run-record.js.map +1 -1
  251. package/dist/prototype-runner.d.ts +2 -2
  252. package/dist/prototype-runner.d.ts.map +1 -1
  253. package/dist/prototype-runner.js +5 -2
  254. package/dist/prototype-runner.js.map +1 -1
  255. package/dist/prototype-workflow-contract.d.ts +13 -0
  256. package/dist/prototype-workflow-contract.d.ts.map +1 -0
  257. package/dist/prototype-workflow-contract.js +82 -0
  258. package/dist/prototype-workflow-contract.js.map +1 -0
  259. package/dist/prototype-workflow-labels.d.ts +29 -0
  260. package/dist/prototype-workflow-labels.d.ts.map +1 -0
  261. package/dist/prototype-workflow-labels.js +93 -0
  262. package/dist/prototype-workflow-labels.js.map +1 -0
  263. package/dist/run-journal-commands.d.ts.map +1 -1
  264. package/dist/run-journal-commands.js +24 -5
  265. package/dist/run-journal-commands.js.map +1 -1
  266. package/dist/scene/camera-model.d.ts +48 -0
  267. package/dist/scene/camera-model.d.ts.map +1 -0
  268. package/dist/scene/camera-model.js +89 -0
  269. package/dist/scene/camera-model.js.map +1 -0
  270. package/dist/scene/camera-solve.d.ts +58 -0
  271. package/dist/scene/camera-solve.d.ts.map +1 -0
  272. package/dist/scene/camera-solve.js +288 -0
  273. package/dist/scene/camera-solve.js.map +1 -0
  274. package/dist/scene/capture-plan.d.ts +28 -0
  275. package/dist/scene/capture-plan.d.ts.map +1 -0
  276. package/dist/scene/capture-plan.js +79 -0
  277. package/dist/scene/capture-plan.js.map +1 -0
  278. package/dist/scene/capture.d.ts +21 -0
  279. package/dist/scene/capture.d.ts.map +1 -0
  280. package/dist/scene/capture.js +118 -0
  281. package/dist/scene/capture.js.map +1 -0
  282. package/dist/scene/image-colors.d.ts +25 -0
  283. package/dist/scene/image-colors.d.ts.map +1 -0
  284. package/dist/scene/image-colors.js +110 -0
  285. package/dist/scene/image-colors.js.map +1 -0
  286. package/dist/scene/image-rectify.d.ts +25 -0
  287. package/dist/scene/image-rectify.d.ts.map +1 -0
  288. package/dist/scene/image-rectify.js +82 -0
  289. package/dist/scene/image-rectify.js.map +1 -0
  290. package/dist/scene/image-sheet.d.ts +19 -0
  291. package/dist/scene/image-sheet.d.ts.map +1 -0
  292. package/dist/scene/image-sheet.js +118 -0
  293. package/dist/scene/image-sheet.js.map +1 -0
  294. package/dist/scene/least-squares.d.ts +31 -0
  295. package/dist/scene/least-squares.d.ts.map +1 -0
  296. package/dist/scene/least-squares.js +173 -0
  297. package/dist/scene/least-squares.js.map +1 -0
  298. package/dist/scene/numbers.d.ts +17 -0
  299. package/dist/scene/numbers.d.ts.map +1 -0
  300. package/dist/scene/numbers.js +39 -0
  301. package/dist/scene/numbers.js.map +1 -0
  302. package/dist/scene/placement.d.ts +43 -0
  303. package/dist/scene/placement.d.ts.map +1 -0
  304. package/dist/scene/placement.js +107 -0
  305. package/dist/scene/placement.js.map +1 -0
  306. package/dist/scene/raster.d.ts +18 -0
  307. package/dist/scene/raster.d.ts.map +1 -0
  308. package/dist/scene/raster.js +31 -0
  309. package/dist/scene/raster.js.map +1 -0
  310. package/dist/scene/scene-kit.d.ts +20 -0
  311. package/dist/scene/scene-kit.d.ts.map +1 -0
  312. package/dist/scene/scene-kit.js +74 -0
  313. package/dist/scene/scene-kit.js.map +1 -0
  314. package/dist/scene/scene-verbs.d.ts +4 -0
  315. package/dist/scene/scene-verbs.d.ts.map +1 -0
  316. package/dist/scene/scene-verbs.js +5 -0
  317. package/dist/scene/scene-verbs.js.map +1 -0
  318. package/dist/scene/seeded-random.d.ts +20 -0
  319. package/dist/scene/seeded-random.d.ts.map +1 -0
  320. package/dist/scene/seeded-random.js +42 -0
  321. package/dist/scene/seeded-random.js.map +1 -0
  322. package/dist/scene/spec-expression.d.ts +25 -0
  323. package/dist/scene/spec-expression.d.ts.map +1 -0
  324. package/dist/scene/spec-expression.js +234 -0
  325. package/dist/scene/spec-expression.js.map +1 -0
  326. package/dist/scene/static-server.d.ts +13 -0
  327. package/dist/scene/static-server.d.ts.map +1 -0
  328. package/dist/scene/static-server.js +99 -0
  329. package/dist/scene/static-server.js.map +1 -0
  330. package/dist/server.d.ts +22 -2
  331. package/dist/server.d.ts.map +1 -1
  332. package/dist/server.js +44 -8
  333. package/dist/server.js.map +1 -1
  334. package/dist/slate-actions.d.ts +38 -0
  335. package/dist/slate-actions.d.ts.map +1 -0
  336. package/dist/slate-actions.js +102 -0
  337. package/dist/slate-actions.js.map +1 -0
  338. package/dist/slate-annotate.d.ts +36 -0
  339. package/dist/slate-annotate.d.ts.map +1 -0
  340. package/dist/slate-annotate.js +71 -0
  341. package/dist/slate-annotate.js.map +1 -0
  342. package/dist/slate-approvals.d.ts +61 -0
  343. package/dist/slate-approvals.d.ts.map +1 -0
  344. package/dist/slate-approvals.js +153 -0
  345. package/dist/slate-approvals.js.map +1 -0
  346. package/dist/slate-browser-decision.d.ts +30 -0
  347. package/dist/slate-browser-decision.d.ts.map +1 -0
  348. package/dist/slate-browser-decision.js +24 -0
  349. package/dist/slate-browser-decision.js.map +1 -0
  350. package/dist/slate-browser-host-script.d.ts +14 -0
  351. package/dist/slate-browser-host-script.d.ts.map +1 -0
  352. package/dist/slate-browser-host-script.js +125 -0
  353. package/dist/slate-browser-host-script.js.map +1 -0
  354. package/dist/slate-browser-host.d.ts +9 -0
  355. package/dist/slate-browser-host.d.ts.map +1 -0
  356. package/dist/slate-browser-host.js +37 -0
  357. package/dist/slate-browser-host.js.map +1 -0
  358. package/dist/slate-browser-server.d.ts +37 -0
  359. package/dist/slate-browser-server.d.ts.map +1 -0
  360. package/dist/slate-browser-server.js +186 -0
  361. package/dist/slate-browser-server.js.map +1 -0
  362. package/dist/slate-commit.d.ts +28 -0
  363. package/dist/slate-commit.d.ts.map +1 -0
  364. package/dist/slate-commit.js +218 -0
  365. package/dist/slate-commit.js.map +1 -0
  366. package/dist/slate-corpus.d.ts +14 -0
  367. package/dist/slate-corpus.d.ts.map +1 -0
  368. package/dist/slate-corpus.js +32 -0
  369. package/dist/slate-corpus.js.map +1 -0
  370. package/dist/slate-edit-prompt.d.ts +18 -0
  371. package/dist/slate-edit-prompt.d.ts.map +1 -0
  372. package/dist/slate-edit-prompt.js +41 -0
  373. package/dist/slate-edit-prompt.js.map +1 -0
  374. package/dist/slate-edit-runner.d.ts +4 -0
  375. package/dist/slate-edit-runner.d.ts.map +1 -0
  376. package/dist/slate-edit-runner.js +90 -0
  377. package/dist/slate-edit-runner.js.map +1 -0
  378. package/dist/slate-editability.d.ts +20 -0
  379. package/dist/slate-editability.d.ts.map +1 -0
  380. package/dist/slate-editability.js +19 -0
  381. package/dist/slate-editability.js.map +1 -0
  382. package/dist/slate-errors.d.ts +15 -0
  383. package/dist/slate-errors.d.ts.map +1 -0
  384. package/dist/slate-errors.js +21 -0
  385. package/dist/slate-errors.js.map +1 -0
  386. package/dist/slate-handoff-options.d.ts +40 -0
  387. package/dist/slate-handoff-options.d.ts.map +1 -0
  388. package/dist/slate-handoff-options.js +127 -0
  389. package/dist/slate-handoff-options.js.map +1 -0
  390. package/dist/slate-handoff.d.ts +11 -0
  391. package/dist/slate-handoff.d.ts.map +1 -0
  392. package/dist/slate-handoff.js +56 -0
  393. package/dist/slate-handoff.js.map +1 -0
  394. package/dist/slate-ids.d.ts +33 -0
  395. package/dist/slate-ids.d.ts.map +1 -0
  396. package/dist/slate-ids.js +47 -0
  397. package/dist/slate-ids.js.map +1 -0
  398. package/dist/slate-image-executor.d.ts +39 -0
  399. package/dist/slate-image-executor.d.ts.map +1 -0
  400. package/dist/slate-image-executor.js +52 -0
  401. package/dist/slate-image-executor.js.map +1 -0
  402. package/dist/slate-inspiration.d.ts +22 -0
  403. package/dist/slate-inspiration.d.ts.map +1 -0
  404. package/dist/slate-inspiration.js +112 -0
  405. package/dist/slate-inspiration.js.map +1 -0
  406. package/dist/slate-labels.d.ts +11 -0
  407. package/dist/slate-labels.d.ts.map +1 -0
  408. package/dist/slate-labels.js +32 -0
  409. package/dist/slate-labels.js.map +1 -0
  410. package/dist/slate-ledger.d.ts +29 -0
  411. package/dist/slate-ledger.d.ts.map +1 -0
  412. package/dist/slate-ledger.js +65 -0
  413. package/dist/slate-ledger.js.map +1 -0
  414. package/dist/slate-liveness.d.ts +26 -0
  415. package/dist/slate-liveness.d.ts.map +1 -0
  416. package/dist/slate-liveness.js +49 -0
  417. package/dist/slate-liveness.js.map +1 -0
  418. package/dist/slate-local-image.d.ts +19 -0
  419. package/dist/slate-local-image.d.ts.map +1 -0
  420. package/dist/slate-local-image.js +36 -0
  421. package/dist/slate-local-image.js.map +1 -0
  422. package/dist/slate-lock.d.ts +64 -0
  423. package/dist/slate-lock.d.ts.map +1 -0
  424. package/dist/slate-lock.js +178 -0
  425. package/dist/slate-lock.js.map +1 -0
  426. package/dist/slate-paths.d.ts +45 -0
  427. package/dist/slate-paths.d.ts.map +1 -0
  428. package/dist/slate-paths.js +132 -0
  429. package/dist/slate-paths.js.map +1 -0
  430. package/dist/slate-pick.d.ts +29 -0
  431. package/dist/slate-pick.d.ts.map +1 -0
  432. package/dist/slate-pick.js +55 -0
  433. package/dist/slate-pick.js.map +1 -0
  434. package/dist/slate-reference-ids.d.ts +6 -0
  435. package/dist/slate-reference-ids.d.ts.map +1 -0
  436. package/dist/slate-reference-ids.js +17 -0
  437. package/dist/slate-reference-ids.js.map +1 -0
  438. package/dist/slate-reference-store.d.ts +23 -0
  439. package/dist/slate-reference-store.d.ts.map +1 -0
  440. package/dist/slate-reference-store.js +46 -0
  441. package/dist/slate-reference-store.js.map +1 -0
  442. package/dist/slate-resume.d.ts +19 -0
  443. package/dist/slate-resume.d.ts.map +1 -0
  444. package/dist/slate-resume.js +94 -0
  445. package/dist/slate-resume.js.map +1 -0
  446. package/dist/slate-round-params.d.ts +20 -0
  447. package/dist/slate-round-params.d.ts.map +1 -0
  448. package/dist/slate-round-params.js +32 -0
  449. package/dist/slate-round-params.js.map +1 -0
  450. package/dist/slate-round-prompt.d.ts +18 -0
  451. package/dist/slate-round-prompt.d.ts.map +1 -0
  452. package/dist/slate-round-prompt.js +20 -0
  453. package/dist/slate-round-prompt.js.map +1 -0
  454. package/dist/slate-round-runner.d.ts +4 -0
  455. package/dist/slate-round-runner.d.ts.map +1 -0
  456. package/dist/slate-round-runner.js +125 -0
  457. package/dist/slate-round-runner.js.map +1 -0
  458. package/dist/slate-round-search.d.ts +7 -0
  459. package/dist/slate-round-search.d.ts.map +1 -0
  460. package/dist/slate-round-search.js +77 -0
  461. package/dist/slate-round-search.js.map +1 -0
  462. package/dist/slate-run-action.d.ts +14 -0
  463. package/dist/slate-run-action.d.ts.map +1 -0
  464. package/dist/slate-run-action.js +81 -0
  465. package/dist/slate-run-action.js.map +1 -0
  466. package/dist/slate-runner-context.d.ts +57 -0
  467. package/dist/slate-runner-context.d.ts.map +1 -0
  468. package/dist/slate-runner-context.js +79 -0
  469. package/dist/slate-runner-context.js.map +1 -0
  470. package/dist/slate-runner-failure.d.ts +8 -0
  471. package/dist/slate-runner-failure.d.ts.map +1 -0
  472. package/dist/slate-runner-failure.js +17 -0
  473. package/dist/slate-runner-failure.js.map +1 -0
  474. package/dist/slate-runner-flag.d.ts +3 -0
  475. package/dist/slate-runner-flag.d.ts.map +1 -0
  476. package/dist/slate-runner-flag.js +3 -0
  477. package/dist/slate-runner-flag.js.map +1 -0
  478. package/dist/slate-runner-main.d.ts +31 -0
  479. package/dist/slate-runner-main.d.ts.map +1 -0
  480. package/dist/slate-runner-main.js +132 -0
  481. package/dist/slate-runner-main.js.map +1 -0
  482. package/dist/slate-runner-spawn.d.ts +23 -0
  483. package/dist/slate-runner-spawn.d.ts.map +1 -0
  484. package/dist/slate-runner-spawn.js +27 -0
  485. package/dist/slate-runner-spawn.js.map +1 -0
  486. package/dist/slate-runtime.d.ts +38 -0
  487. package/dist/slate-runtime.d.ts.map +1 -0
  488. package/dist/slate-runtime.js +48 -0
  489. package/dist/slate-runtime.js.map +1 -0
  490. package/dist/slate-versions.d.ts +26 -0
  491. package/dist/slate-versions.d.ts.map +1 -0
  492. package/dist/slate-versions.js +110 -0
  493. package/dist/slate-versions.js.map +1 -0
  494. package/dist/slate-view-contract.d.ts +233 -0
  495. package/dist/slate-view-contract.d.ts.map +1 -0
  496. package/dist/slate-view-contract.js +17 -0
  497. package/dist/slate-view-contract.js.map +1 -0
  498. package/dist/slate-view-types.d.ts +2 -0
  499. package/dist/slate-view-types.d.ts.map +1 -0
  500. package/dist/slate-view-types.js +2 -0
  501. package/dist/slate-view-types.js.map +1 -0
  502. package/dist/slate-view.d.ts +19 -0
  503. package/dist/slate-view.d.ts.map +1 -0
  504. package/dist/slate-view.js +184 -0
  505. package/dist/slate-view.js.map +1 -0
  506. package/dist/slate-workspace-parse.d.ts +20 -0
  507. package/dist/slate-workspace-parse.d.ts.map +1 -0
  508. package/dist/slate-workspace-parse.js +437 -0
  509. package/dist/slate-workspace-parse.js.map +1 -0
  510. package/dist/slate-workspace-store.d.ts +44 -0
  511. package/dist/slate-workspace-store.d.ts.map +1 -0
  512. package/dist/slate-workspace-store.js +270 -0
  513. package/dist/slate-workspace-store.js.map +1 -0
  514. package/dist/slate-workspace-types.d.ts +176 -0
  515. package/dist/slate-workspace-types.d.ts.map +1 -0
  516. package/dist/slate-workspace-types.js +13 -0
  517. package/dist/slate-workspace-types.js.map +1 -0
  518. package/dist/workflow/adapter-12ui.d.ts +4 -0
  519. package/dist/workflow/adapter-12ui.d.ts.map +1 -0
  520. package/dist/workflow/adapter-12ui.js +147 -0
  521. package/dist/workflow/adapter-12ui.js.map +1 -0
  522. package/dist/workflow/adapter-layerdoc.d.ts +16 -0
  523. package/dist/workflow/adapter-layerdoc.d.ts.map +1 -0
  524. package/dist/workflow/adapter-layerdoc.js +116 -0
  525. package/dist/workflow/adapter-layerdoc.js.map +1 -0
  526. package/dist/workflow/adapter-openai.d.ts +4 -0
  527. package/dist/workflow/adapter-openai.d.ts.map +1 -0
  528. package/dist/workflow/adapter-openai.js +166 -0
  529. package/dist/workflow/adapter-openai.js.map +1 -0
  530. package/dist/workflow/adapter-process.d.ts +7 -0
  531. package/dist/workflow/adapter-process.d.ts.map +1 -0
  532. package/dist/workflow/adapter-process.js +174 -0
  533. package/dist/workflow/adapter-process.js.map +1 -0
  534. package/dist/workflow/adapter-prototype-labels.d.ts +15 -0
  535. package/dist/workflow/adapter-prototype-labels.d.ts.map +1 -0
  536. package/dist/workflow/adapter-prototype-labels.js +71 -0
  537. package/dist/workflow/adapter-prototype-labels.js.map +1 -0
  538. package/dist/workflow/adapter-types.d.ts +40 -0
  539. package/dist/workflow/adapter-types.d.ts.map +1 -0
  540. package/dist/workflow/adapter-types.js +2 -0
  541. package/dist/workflow/adapter-types.js.map +1 -0
  542. package/dist/workflow/adapter-utils.d.ts +11 -0
  543. package/dist/workflow/adapter-utils.d.ts.map +1 -0
  544. package/dist/workflow/adapter-utils.js +72 -0
  545. package/dist/workflow/adapter-utils.js.map +1 -0
  546. package/dist/workflow/adapters.d.ts +6 -0
  547. package/dist/workflow/adapters.d.ts.map +1 -0
  548. package/dist/workflow/adapters.js +25 -0
  549. package/dist/workflow/adapters.js.map +1 -0
  550. package/dist/workflow/artifact.d.ts +11 -0
  551. package/dist/workflow/artifact.d.ts.map +1 -0
  552. package/dist/workflow/artifact.js +94 -0
  553. package/dist/workflow/artifact.js.map +1 -0
  554. package/dist/workflow/bundle-collect.d.ts +8 -0
  555. package/dist/workflow/bundle-collect.d.ts.map +1 -0
  556. package/dist/workflow/bundle-collect.js +56 -0
  557. package/dist/workflow/bundle-collect.js.map +1 -0
  558. package/dist/workflow/bundle-export.d.ts +16 -0
  559. package/dist/workflow/bundle-export.d.ts.map +1 -0
  560. package/dist/workflow/bundle-export.js +174 -0
  561. package/dist/workflow/bundle-export.js.map +1 -0
  562. package/dist/workflow/bundle-paths.d.ts +7 -0
  563. package/dist/workflow/bundle-paths.d.ts.map +1 -0
  564. package/dist/workflow/bundle-paths.js +35 -0
  565. package/dist/workflow/bundle-paths.js.map +1 -0
  566. package/dist/workflow/bundle.d.ts +4 -0
  567. package/dist/workflow/bundle.d.ts.map +1 -0
  568. package/dist/workflow/bundle.js +4 -0
  569. package/dist/workflow/bundle.js.map +1 -0
  570. package/dist/workflow/capture.d.ts +36 -0
  571. package/dist/workflow/capture.d.ts.map +1 -0
  572. package/dist/workflow/capture.js +81 -0
  573. package/dist/workflow/capture.js.map +1 -0
  574. package/dist/workflow/continuation-branch.d.ts +15 -0
  575. package/dist/workflow/continuation-branch.d.ts.map +1 -0
  576. package/dist/workflow/continuation-branch.js +103 -0
  577. package/dist/workflow/continuation-branch.js.map +1 -0
  578. package/dist/workflow/continuation-plans.d.ts +38 -0
  579. package/dist/workflow/continuation-plans.d.ts.map +1 -0
  580. package/dist/workflow/continuation-plans.js +78 -0
  581. package/dist/workflow/continuation-plans.js.map +1 -0
  582. package/dist/workflow/continuation.d.ts +25 -0
  583. package/dist/workflow/continuation.d.ts.map +1 -0
  584. package/dist/workflow/continuation.js +89 -0
  585. package/dist/workflow/continuation.js.map +1 -0
  586. package/dist/workflow/layerdoc-reader.d.ts +27 -0
  587. package/dist/workflow/layerdoc-reader.d.ts.map +1 -0
  588. package/dist/workflow/layerdoc-reader.js +81 -0
  589. package/dist/workflow/layerdoc-reader.js.map +1 -0
  590. package/dist/workflow/project-evidence.d.ts +48 -0
  591. package/dist/workflow/project-evidence.d.ts.map +1 -0
  592. package/dist/workflow/project-evidence.js +200 -0
  593. package/dist/workflow/project-evidence.js.map +1 -0
  594. package/dist/workflow/providers.d.ts +35 -0
  595. package/dist/workflow/providers.d.ts.map +1 -0
  596. package/dist/workflow/providers.js +110 -0
  597. package/dist/workflow/providers.js.map +1 -0
  598. package/dist/workflow/recipes-layerdoc-validation.d.ts +4 -0
  599. package/dist/workflow/recipes-layerdoc-validation.d.ts.map +1 -0
  600. package/dist/workflow/recipes-layerdoc-validation.js +98 -0
  601. package/dist/workflow/recipes-layerdoc-validation.js.map +1 -0
  602. package/dist/workflow/recipes-result-validation.d.ts +6 -0
  603. package/dist/workflow/recipes-result-validation.d.ts.map +1 -0
  604. package/dist/workflow/recipes-result-validation.js +38 -0
  605. package/dist/workflow/recipes-result-validation.js.map +1 -0
  606. package/dist/workflow/recipes-schemas.d.ts +7 -0
  607. package/dist/workflow/recipes-schemas.d.ts.map +1 -0
  608. package/dist/workflow/recipes-schemas.js +67 -0
  609. package/dist/workflow/recipes-schemas.js.map +1 -0
  610. package/dist/workflow/recipes-validation.d.ts +14 -0
  611. package/dist/workflow/recipes-validation.d.ts.map +1 -0
  612. package/dist/workflow/recipes-validation.js +68 -0
  613. package/dist/workflow/recipes-validation.js.map +1 -0
  614. package/dist/workflow/recipes.d.ts +20 -0
  615. package/dist/workflow/recipes.d.ts.map +1 -0
  616. package/dist/workflow/recipes.js +167 -0
  617. package/dist/workflow/recipes.js.map +1 -0
  618. package/dist/workflow/routing.d.ts +4 -0
  619. package/dist/workflow/routing.d.ts.map +1 -0
  620. package/dist/workflow/routing.js +28 -0
  621. package/dist/workflow/routing.js.map +1 -0
  622. package/dist/workflow/schema.d.ts +5 -0
  623. package/dist/workflow/schema.d.ts.map +1 -0
  624. package/dist/workflow/schema.js +29 -0
  625. package/dist/workflow/schema.js.map +1 -0
  626. package/dist/workflow/service.d.ts +59 -0
  627. package/dist/workflow/service.d.ts.map +1 -0
  628. package/dist/workflow/service.js +170 -0
  629. package/dist/workflow/service.js.map +1 -0
  630. package/dist/workflow/store-json.d.ts +5 -0
  631. package/dist/workflow/store-json.d.ts.map +1 -0
  632. package/dist/workflow/store-json.js +35 -0
  633. package/dist/workflow/store-json.js.map +1 -0
  634. package/dist/workflow/store-lock.d.ts +3 -0
  635. package/dist/workflow/store-lock.d.ts.map +1 -0
  636. package/dist/workflow/store-lock.js +85 -0
  637. package/dist/workflow/store-lock.js.map +1 -0
  638. package/dist/workflow/store-paths.d.ts +17 -0
  639. package/dist/workflow/store-paths.d.ts.map +1 -0
  640. package/dist/workflow/store-paths.js +67 -0
  641. package/dist/workflow/store-paths.js.map +1 -0
  642. package/dist/workflow/store-validation.d.ts +7 -0
  643. package/dist/workflow/store-validation.d.ts.map +1 -0
  644. package/dist/workflow/store-validation.js +119 -0
  645. package/dist/workflow/store-validation.js.map +1 -0
  646. package/dist/workflow/store.d.ts +10 -0
  647. package/dist/workflow/store.d.ts.map +1 -0
  648. package/dist/workflow/store.js +193 -0
  649. package/dist/workflow/store.js.map +1 -0
  650. package/dist/workflow/types.d.ts +120 -0
  651. package/dist/workflow/types.d.ts.map +1 -0
  652. package/dist/workflow/types.js +15 -0
  653. package/dist/workflow/types.js.map +1 -0
  654. package/dist/workflow-transport.d.ts +28 -0
  655. package/dist/workflow-transport.d.ts.map +1 -0
  656. package/dist/workflow-transport.js +184 -0
  657. package/dist/workflow-transport.js.map +1 -0
  658. package/open-design.json +2 -2
  659. package/package.json +4 -1
  660. package/prototype-kit/tests/rules-check.mjs +9 -0
  661. package/runtime/codex-conversion/src/images/native-invoke.mjs +1 -1
  662. package/runtime/codex-conversion/src/images/native.mjs +8 -4
  663. package/runtime/layerdoc-validator.mjs +1860 -0
  664. package/scene-kit/starter/camera.js +10 -0
  665. package/scene-kit/starter/gobo.js +60 -0
  666. package/scene-kit/starter/index.html +23 -0
  667. package/scene-kit/starter/lib.js +84 -0
  668. package/scene-kit/starter/main.js +78 -0
  669. package/scene-kit/starter/scene.js +33 -0
  670. package/scene-kit/vendor/LICENSE +21 -0
  671. package/scene-kit/vendor/addons/geometries/RoundedBoxGeometry.js +216 -0
  672. package/scene-kit/vendor/addons/renderers/CSS3DRenderer.js +454 -0
  673. package/scene-kit/vendor/three.core.js +60586 -0
  674. package/scene-kit/vendor/three.module.js +19719 -0
  675. package/skills/12ui-design/SKILL.md +21 -61
  676. package/skills/12ui-design/improve.md +5 -1
  677. package/skills/12ui-design/inspire.md +8 -5
  678. package/skills/12ui-design/outputs.md +23 -2
  679. package/skills/12ui-design/scene.md +172 -0
  680. package/skills/12ui-design/session.md +161 -0
@@ -0,0 +1,10 @@
1
+ // Paste the "camera.js" line from `12ui scene solve spec.json --out cam.json` here. It uses the same keys and units as cam.json:
2
+ // yawDeg / pitchDeg / rollDeg / vfov are DEGREES (main.js converts to radians). Scene units are yours.
3
+ export const FRAME = { w: 1536, h: 1024 }; // source image size = design frame
4
+ export const CAM = { pos: [0, 2, 6], yawDeg: 0, pitchDeg: -11, rollDeg: 0, vfov: 30 };
5
+ // Depth range: tight. Keep far/near under ~100 or headless GL z-fights (edge-on cylinder walls, decals sitting 1 mm off a
6
+ // surface, shadow-map leaks that show as dotted arcs). The solver prints a "clip" for this camera; also keep coincident
7
+ // surfaces at least ~0.002 x the camera distance apart, and give thin parts real thickness or a chamfered rim.
8
+ export const CLIP = { near: 0.5, far: 60 };
9
+ export const PIVOT = [0, 0, 0]; // orbit centre: where the optical axis meets the subject
10
+ export const ORBIT_LIMIT = 15; // degrees each way for pointer/drag orbit
@@ -0,0 +1,60 @@
1
+ // Window light, leaf shadows, dappled patterns: a SpotLight with `.map` (a gobo). The pattern is DRAWN IN SOURCE-IMAGE
2
+ // PIXELS (where the shadows sit in the design) and resampled through the solved camera onto the surface plane, so it lands
3
+ // exactly where drawn at the landing view but is real light: it darkens whatever stands there and moves with the orbit.
4
+ //
5
+ // const spot = new THREE.SpotLight(0xfff1e0, 900, 0, 0.6, 0.7, 2); // angle = half-angle: it must cover the whole visible surface
6
+ // spot.position.set(-2, 8, 3); spot.target.position.set(0.5, 0, 0); spot.castShadow = true; // .map is ignored unless castShadow is true
7
+ // scene.add(spot, spot.target);
8
+ // spot.map = goboTexture(spot, (g, w, h) => { g.fillStyle = '#fff'; g.fillRect(0, 0, w, h); // white = light, dark = shadow
9
+ // g.filter = 'blur(38px)'; g.fillStyle = 'rgba(120,98,86,0.5)'; /* draw shadow shapes at source pixel coordinates */ });
10
+ //
11
+ // Orientation, pinned down: texture rows run from the spot's view-bottom (row 0) to view-top, flipY = false, and the pattern
12
+ // is written through CAM (camera.js), not through the light. So DO NOT flip or mirror anything by hand. Verify once by
13
+ // drawing a bright red square at a known source pixel (say the top-left of the sleeve) and checking that it lands there.
14
+ // Draw past the frame edges: outside the source frame the edge value is held, so patterns fade instead of ending in a seam.
15
+ import * as THREE from 'three';
16
+ import { CAM, FRAME } from './camera.js';
17
+ import { rng } from './lib.js';
18
+
19
+ const D2R = THREE.MathUtils.degToRad;
20
+
21
+ export function goboTexture(light, draw, { size = 1536, planeY = 0 } = {}) {
22
+ const src = document.createElement('canvas'); src.width = FRAME.w; src.height = FRAME.h;
23
+ draw(src.getContext('2d'), FRAME.w, FRAME.h);
24
+ const sd = src.getContext('2d').getImageData(0, 0, FRAME.w, FRAME.h).data;
25
+ const P = light.position.clone(), T = light.target.position.clone();
26
+ const f = T.clone().sub(P).normalize();
27
+ const right = new THREE.Vector3().crossVectors(f, new THREE.Vector3(0, 1, 0)).normalize(), up = new THREE.Vector3().crossVectors(right, f);
28
+ const th = Math.tan(light.angle);
29
+ const q = new THREE.Quaternion().setFromEuler(new THREE.Euler(D2R(CAM.pitchDeg), D2R(CAM.yawDeg), D2R(CAM.rollDeg), 'YXZ')).invert();
30
+ const F = (FRAME.h / 2) / Math.tan(D2R(CAM.vfov) / 2), cp = new THREE.Vector3(...CAM.pos), d = new THREE.Vector3(), c = new THREE.Vector3();
31
+ const out = document.createElement('canvas'); out.width = out.height = size;
32
+ const og = out.getContext('2d'), od = og.createImageData(size, size);
33
+ for (let j = 0; j < size; j++) for (let i = 0; i < size; i++) {
34
+ const x = 2 * (i + 0.5) / size - 1, y = 2 * (j + 0.5) / size - 1;
35
+ d.copy(f).addScaledVector(right, x * th).addScaledVector(up, y * th);
36
+ let v = 255;
37
+ if (d.y < -1e-4) { // ray from the light hits the plane y = planeY
38
+ const t = (planeY - P.y) / d.y;
39
+ c.set(P.x + d.x * t, planeY, P.z + d.z * t).sub(cp).applyQuaternion(q); // world -> camera
40
+ const u = FRAME.w / 2 + F * c.x / -c.z, w = FRAME.h / 2 - F * c.y / -c.z;
41
+ const ux = Math.min(FRAME.w - 1, Math.max(0, Math.round(u))), uy = Math.min(FRAME.h - 1, Math.max(0, Math.round(w)));
42
+ v = sd[(uy * FRAME.w + ux) * 4];
43
+ }
44
+ const o = (j * size + i) * 4; od.data[o] = od.data[o + 1] = od.data[o + 2] = v; od.data[o + 3] = 255;
45
+ }
46
+ og.putImageData(od, 0, 0);
47
+ const t = new THREE.CanvasTexture(out); t.flipY = false; t.colorSpace = THREE.SRGBColorSpace; return t;
48
+ }
49
+
50
+ // One leaf/frond as ONE path segment set. Call several times between g.beginPath() and a single g.fill() so overlapping
51
+ // leaflets union into one shadow (separate fills stack and read as dark blotches).
52
+ export function frond(g, x, y, ang, len, wid, seed = 4) {
53
+ const r = rng(seed + Math.round(x + y)); g.save(); g.translate(x, y); g.rotate(ang);
54
+ g.moveTo(0, 0); g.quadraticCurveTo(len * 0.5, -len * 0.03, len, 0); g.quadraticCurveTo(len * 0.5, len * 0.03, 0, 0);
55
+ for (let i = 0; i < 6; i++) {
56
+ const t = 0.2 + i * 0.13, px = len * t, l = len * 0.36 * Math.sin(Math.PI * (0.1 + t * 0.8));
57
+ for (const s of [-1, 1]) { g.save(); g.translate(px, 0); g.rotate(s * (0.95 + r() * 0.2)); g.moveTo(l, 0); g.ellipse(l / 2, 0, l / 2, wid * (0.8 + r() * 0.4), 0, 0, 7); g.restore(); }
58
+ }
59
+ g.restore();
60
+ }
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Scene</title>
7
+ <style>
8
+ html, body { margin: 0; height: 100%; overflow: hidden; background: #000; }
9
+ canvas#gl { position: fixed; inset: 0; width: 100%; height: 100%; display: block; }
10
+ /* #stage is the source image's pixel frame; main.js scales it to sit exactly over the contain-fitted canvas */
11
+ #stage { position: fixed; left: 0; top: 0; width: 1536px; height: 1024px; transform-origin: 0 0; pointer-events: none; }
12
+ #stage a, #stage button, #stage [data-hit] { pointer-events: auto; }
13
+ /* real page text goes here, positioned in source pixels, e.g.
14
+ <h1 style="position:absolute; left:56px; top:232px; font: 800 78px/0.9 'Chivo', sans-serif">TITLE</h1> */
15
+ </style>
16
+ <script type="importmap">{ "imports": { "three": "./vendor/three.module.js", "three/addons/": "./vendor/addons/" } }</script>
17
+ </head>
18
+ <body>
19
+ <canvas id="gl"></canvas>
20
+ <div id="stage"></div>
21
+ <script type="module" src="./main.js"></script>
22
+ </body>
23
+ </html>
@@ -0,0 +1,84 @@
1
+ // Small helpers that every scene needs. Keep scene code in scene.js and friends, not here.
2
+ import * as THREE from 'three';
3
+
4
+ export const rng = (seed) => { let s = seed >>> 0; return () => ((s = (s * 1664525 + 1013904223) >>> 0) / 4294967296); };
5
+
6
+ export function canvasTex(w, h, draw, { srgb = true, repeat = null } = {}) {
7
+ const c = document.createElement('canvas'); c.width = w; c.height = h;
8
+ draw(c.getContext('2d'), w, h);
9
+ const t = new THREE.CanvasTexture(c);
10
+ t.colorSpace = srgb ? THREE.SRGBColorSpace : THREE.NoColorSpace; t.anisotropy = 8;
11
+ if (repeat) { t.wrapS = t.wrapT = THREE.RepeatWrapping; t.repeat.set(...repeat); }
12
+ return t;
13
+ }
14
+
15
+ // Speckle + fibre grain over an already-filled canvas: paper, kraft, plaster, concrete.
16
+ export function grain(g, w, h, { amount = 18, seed = 1 } = {}) {
17
+ const r = rng(seed), id = g.getImageData(0, 0, w, h), p = id.data;
18
+ for (let i = 0; i < p.length; i += 4) { const n = (r() - 0.5) * amount; p[i] += n; p[i + 1] += n; p[i + 2] += n; }
19
+ g.putImageData(id, 0, 0);
20
+ }
21
+
22
+ // Rounded-rectangle slab (book board, drive, card, phone, sleeve). Cap UVs run 0..1 over the face so a printed
23
+ // texture lands where drawn: u = x/w + .5, v = y/h + .5. Face points +z.
24
+ export function slabGeometry(w, h, t, r, bevel = Math.min(t * 0.3, 0.012)) {
25
+ const x = -w / 2, y = -h / 2, s = new THREE.Shape();
26
+ r = Math.min(r, w / 2 - 1e-3, h / 2 - 1e-3);
27
+ s.moveTo(x + r, y); s.lineTo(x + w - r, y); s.absarc(x + w - r, y + r, r, -Math.PI / 2, 0, false);
28
+ s.lineTo(x + w, y + h - r); s.absarc(x + w - r, y + h - r, r, 0, Math.PI / 2, false);
29
+ s.lineTo(x + r, y + h); s.absarc(x + r, y + h - r, r, Math.PI / 2, Math.PI, false);
30
+ s.lineTo(x, y + r); s.absarc(x + r, y + r, r, Math.PI, Math.PI * 1.5, false);
31
+ const g = new THREE.ExtrudeGeometry(s, { depth: t - 2 * bevel, bevelEnabled: true, bevelSize: bevel, bevelThickness: bevel, bevelSegments: 3, curveSegments: 12 });
32
+ g.translate(0, 0, -(t - 2 * bevel) / 2);
33
+ const pos = g.attributes.position, uv = g.attributes.uv, nor = g.attributes.normal;
34
+ for (let i = 0; i < pos.count; i++) if (Math.abs(nor.getZ(i)) > 0.9) uv.setXY(i, pos.getX(i) / w + 0.5, pos.getY(i) / h + 0.5);
35
+ return g;
36
+ }
37
+
38
+ // Soft dark blob under an object: cheap, always reads as "sitting on" the surface. Add to the scene at floor level.
39
+ export function contactShadow(w, d, { opacity = 0.6, y = 0 } = {}) {
40
+ const c = document.createElement('canvas'); c.width = c.height = 128; const g = c.getContext('2d');
41
+ const gr = g.createRadialGradient(64, 64, 8, 64, 64, 64); gr.addColorStop(0, 'rgba(0,0,0,1)'); gr.addColorStop(0.6, 'rgba(0,0,0,0.55)'); gr.addColorStop(1, 'rgba(0,0,0,0)');
42
+ g.fillStyle = gr; g.fillRect(0, 0, 128, 128);
43
+ const m = new THREE.Mesh(new THREE.PlaneGeometry(w, d), new THREE.MeshBasicMaterial({ map: new THREE.CanvasTexture(c), transparent: true, depthWrite: false, opacity }));
44
+ m.rotation.x = -Math.PI / 2; m.position.y = y + 0.002; m.renderOrder = 2; return m;
45
+ }
46
+
47
+ // Blurred glossy floor reflection without Reflector: mirrored, jittered, fading copies of chosen meshes.
48
+ // Call the returned function every frame (after actions move things). Floor must be y = floorY and must not write depth
49
+ // (mat.depthWrite = false; mesh.renderOrder = -2). blur grows the smear; fade is the height at which it vanishes.
50
+ const TAPS = [[0, 0], [0.9, 0.4], [-0.9, -0.4], [0.5, -0.9], [-0.5, 0.9], [1.4, -0.2], [-1.4, 0.2]];
51
+ export function reflections(sources, scene, floorY, { opacity = 0.5, blur = 0.04, fade = 1.5 } = {}) {
52
+ const base = new THREE.Matrix4().makeTranslation(0, 2 * floorY, 0).multiply(new THREE.Matrix4().makeScale(1, -1, 1));
53
+ const perTap = 1 - Math.pow(1 - opacity, 1 / TAPS.length), pairs = [];
54
+ for (const src of sources) {
55
+ for (const [tx, tz] of TAPS) {
56
+ const mats = (Array.isArray(src.material) ? src.material : [src.material]).map((sm) => {
57
+ const c = sm.clone(); c.transparent = true; c.depthWrite = false; c.bumpMap = null;
58
+ c.onBeforeCompile = (sh) => {
59
+ sh.uniforms.uFloorY = { value: floorY }; sh.uniforms.uFade = { value: fade }; sh.uniforms.uOp = { value: perTap };
60
+ sh.vertexShader = sh.vertexShader.replace('#include <common>', '#include <common>\nvarying float vRefY;').replace('#include <begin_vertex>', '#include <begin_vertex>\nvRefY = (modelMatrix * vec4(transformed,1.0)).y;');
61
+ sh.fragmentShader = sh.fragmentShader.replace('#include <common>', '#include <common>\nvarying float vRefY; uniform float uFloorY; uniform float uFade; uniform float uOp;')
62
+ .replace('#include <dithering_fragment>', 'float dd = clamp((uFloorY - vRefY)/uFade, 0.0, 1.0);\n gl_FragColor.a *= uOp * pow(1.0 - dd, 1.6);\n#include <dithering_fragment>');
63
+ };
64
+ return c;
65
+ });
66
+ const ref = new THREE.Mesh(src.geometry, Array.isArray(src.material) ? mats : mats[0]);
67
+ ref.matrixAutoUpdate = false; ref.renderOrder = 5; ref.frustumCulled = false; scene.add(ref);
68
+ const sx = tx * blur, sz = tz * blur;
69
+ const shear = new THREE.Matrix4().set(1, -sx, 0, sx * floorY, 0, 1, 0, 0, 0, -sz, 1, sz * floorY, 0, 0, 0, 1);
70
+ pairs.push([src, ref, new THREE.Matrix4().multiplyMatrices(shear, base)]);
71
+ }
72
+ }
73
+ return () => { for (const [s, r, M] of pairs) { s.updateWorldMatrix(true, false); r.matrix.multiplyMatrices(M, s.matrixWorld); r.matrixWorldNeedsUpdate = true; } };
74
+ }
75
+
76
+ // Small procedural studio for glossy surfaces (vinyl, lacquer, glass, metal): dark room, one big soft window, a strip, a top card.
77
+ // Pass renderer (buildScene receives it). Assign to material.envMap on ONLY the objects that should reflect it, so plaster,
78
+ // paper and floor stay lit by the real lights. Move `win` and `strip` to where the source's highlights come from.
79
+ export function studioEnv(renderer, { win = [4.5, 2.6, -1.2], strip = [-3.5, 2.0, -4] } = {}) {
80
+ const s = new THREE.Scene(); s.background = new THREE.Color(0x0b0a09);
81
+ const emit = (w, h, pos, k, tint = 0xffffff) => { const m = new THREE.Mesh(new THREE.PlaneGeometry(w, h), new THREE.MeshBasicMaterial({ color: new THREE.Color(tint).multiplyScalar(k), side: THREE.DoubleSide })); m.position.set(...pos); m.lookAt(0, 0, 0); s.add(m); };
82
+ emit(4.5, 3.4, win, 14, 0xfff1de); emit(6, 1.0, strip, 7, 0xf4efe8); emit(3, 1.6, [0, 4.5, 2], 3.5);
83
+ const pm = new THREE.PMREMGenerator(renderer), env = pm.fromScene(s, 0.02).texture; pm.dispose(); return env;
84
+ }
@@ -0,0 +1,78 @@
1
+ // Harness: renderer, solved camera, contain-fit frame, orbit about the subject, click actions, capture contract.
2
+ // You should not need to edit this beyond the renderer/tone-mapping settings. Scene work goes in scene.js.
3
+ import * as THREE from 'three';
4
+ import { FRAME, CAM, CLIP, PIVOT, ORBIT_LIMIT } from './camera.js';
5
+ import { buildScene } from './scene.js';
6
+
7
+ const canvas = document.getElementById('gl'), stage = document.getElementById('stage');
8
+ const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, preserveDrawingBuffer: true });
9
+ renderer.setPixelRatio(Math.min(devicePixelRatio || 1, 2));
10
+ renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFShadowMap; // PCFSoftShadowMap is removed in three 0.186;
11
+ renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.0; renderer.outputColorSpace = THREE.SRGBColorSpace;
12
+ const scene = new THREE.Scene();
13
+ const camera = new THREE.PerspectiveCamera(CAM.vfov, FRAME.w / FRAME.h, CLIP.near, CLIP.far);
14
+ const built = buildScene(scene, renderer, camera); // renderer: PMREM env maps (lib.studioEnv); camera: gobos, overlays
15
+
16
+ // ---- camera: solved pose, orbit about PIVOT (azimuth about world y, elevation about the camera's right axis)
17
+ const D2R = THREE.MathUtils.degToRad;
18
+ const base = { pos: new THREE.Vector3(...CAM.pos), q: new THREE.Quaternion().setFromEuler(new THREE.Euler(D2R(CAM.pitchDeg), D2R(CAM.yawDeg), D2R(CAM.rollDeg), 'YXZ')) };
19
+ const pivot = new THREE.Vector3(...PIVOT);
20
+ let az = 0, el = 0, azT = 0, elT = 0;
21
+ function applyCamera() {
22
+ const qy = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), THREE.MathUtils.degToRad(az));
23
+ const right = new THREE.Vector3(1, 0, 0).applyQuaternion(qy.clone().multiply(base.q));
24
+ const qe = new THREE.Quaternion().setFromAxisAngle(right, THREE.MathUtils.degToRad(el));
25
+ const rot = qe.clone().multiply(qy);
26
+ camera.position.copy(pivot).add(base.pos.clone().sub(pivot).applyQuaternion(rot));
27
+ camera.quaternion.copy(rot).multiply(base.q);
28
+ camera.updateMatrixWorld(true);
29
+ }
30
+ // contain-fit: the whole source frame stays visible at any window size; #stage (DOM text) is scaled to match
31
+ function resize() {
32
+ const w = innerWidth, h = innerHeight; renderer.setSize(w, h, false);
33
+ const asp = w / h, fa = FRAME.w / FRAME.h, tv = Math.tan(THREE.MathUtils.degToRad(CAM.vfov) / 2);
34
+ camera.aspect = asp; camera.fov = THREE.MathUtils.radToDeg(2 * Math.atan(asp >= fa ? tv : tv * fa / asp)); camera.updateProjectionMatrix();
35
+ const s = Math.min(w / FRAME.w, h / FRAME.h);
36
+ stage.style.width = FRAME.w + 'px'; stage.style.height = FRAME.h + 'px';
37
+ stage.style.transform = `translate(${(w - FRAME.w * s) / 2}px, ${(h - FRAME.h * s) / 2}px) scale(${s})`;
38
+ }
39
+ addEventListener('resize', resize); resize();
40
+
41
+ // ---- actions: click a picked mesh to toggle; buttons in #stage can call __scene.toggle(name)
42
+ const actions = built.actions, state = {};
43
+ for (const k of Object.keys(actions)) state[k] = { t: 0, target: 0 };
44
+ const owner = new Map();
45
+ for (const [k, a] of Object.entries(actions)) for (const m of a.pick || []) m.traverse((o) => o.isMesh && owner.set(o, k));
46
+ const ray = new THREE.Raycaster(), ndc = new THREE.Vector2();
47
+ const pick = (e) => { ndc.set((e.clientX / innerWidth) * 2 - 1, -((e.clientY / innerHeight) * 2 - 1)); ray.setFromCamera(ndc, camera); const h = ray.intersectObjects([...owner.keys()], false)[0]; return h && owner.get(h.object); };
48
+ const toggle = (k) => { state[k].target = state[k].target > 0.5 ? 0 : 1; };
49
+ let drag = null;
50
+ addEventListener('pointerdown', (e) => { drag = { x: e.clientX, moved: 0, a: azT }; });
51
+ addEventListener('pointermove', (e) => {
52
+ if (drag) { drag.moved = Math.max(drag.moved, Math.abs(e.clientX - drag.x)); azT = THREE.MathUtils.clamp(drag.a + (e.clientX - drag.x) * 0.08, -ORBIT_LIMIT, ORBIT_LIMIT); }
53
+ else canvas.style.cursor = pick(e) ? 'pointer' : 'default';
54
+ });
55
+ addEventListener('pointerup', (e) => { if (drag && drag.moved < 5) { const k = pick(e); if (k) toggle(k); } drag = null; });
56
+ addEventListener('keydown', (e) => { if (e.key === 'ArrowLeft') azT = Math.max(-ORBIT_LIMIT, azT - 5); if (e.key === 'ArrowRight') azT = Math.min(ORBIT_LIMIT, azT + 5); });
57
+
58
+ const ease = (t) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2);
59
+ function frame(dt) {
60
+ az += (azT - az) * Math.min(1, dt * 8); el += (elT - el) * Math.min(1, dt * 8);
61
+ for (const [k, s] of Object.entries(state)) if (Math.abs(s.target - s.t) > 1e-3) { s.t += Math.sign(s.target - s.t) * Math.min(Math.abs(s.target - s.t), dt * 1.4); actions[k].apply(ease(s.t)); }
62
+ built.update(dt); applyCamera(); renderer.render(scene, camera);
63
+ }
64
+ let last = performance.now();
65
+ (function loop(now) { frame(Math.min(0.05, (now - last) / 1000)); last = now; requestAnimationFrame(loop); })(last);
66
+
67
+ // ---- capture contract (`12ui scene capture`)
68
+ window.__scene = {
69
+ scene, camera, renderer, actions: Object.keys(actions), toggle,
70
+ setOrbit(a, e = 0) { az = azT = a; el = elT = e; },
71
+ setAction(k, t) { state[k].t = state[k].target = t; actions[k].apply(t); },
72
+ // debug/visibility: hide or show scene objects by name substring (name your groups). `12ui scene capture --hide a,b` uses this.
73
+ setVisible(pattern, on = true) { let n = 0; scene.traverse((o) => { if (o.name && o.name.includes(pattern)) { o.visible = on; n++; } }); return n; },
74
+ names() { const a = []; scene.traverse((o) => o.name && a.push(o.name)); return a; },
75
+ reset() { for (const k of Object.keys(actions)) this.setAction(k, 0); this.setOrbit(0, 0); },
76
+ render() { frame(0); },
77
+ };
78
+ document.fonts.ready.then(() => { window.__ready = true; });
@@ -0,0 +1,33 @@
1
+ // Replace this demo with the recreation. Contract with main.js: build the scene, return
2
+ // Name groups and key meshes (obj.name = 'vinyl') so `12ui scene capture --hide vinyl` can isolate them when debugging.
3
+ // { actions: { name: { label, apply(t) /* t in 0..1, pose ONE object */, pick: [meshes] } },
4
+ // update(dt) /* per-frame extras: reflections, animated bits */ }
5
+ import * as THREE from 'three';
6
+ import { canvasTex, grain, contactShadow } from './lib.js';
7
+
8
+ export function buildScene(scene, renderer, camera) { // renderer for PMREM (studioEnv), camera for gobos
9
+ scene.background = new THREE.Color(0x14110f);
10
+ const key = new THREE.DirectionalLight(0xfff1e0, 2.4); key.position.set(-3, 5, 4); key.castShadow = true;
11
+ key.shadow.mapSize.set(2048, 2048); key.shadow.bias = -0.0004; key.shadow.normalBias = 0.02;
12
+ Object.assign(key.shadow.camera, { left: -4, right: 4, top: 4, bottom: -4, near: 0.5, far: 20 });
13
+ scene.add(key, new THREE.HemisphereLight(0x9aa4b4, 0x30231a, 0.5));
14
+
15
+ const floor = new THREE.Mesh(new THREE.PlaneGeometry(40, 40), new THREE.MeshStandardMaterial({
16
+ color: 0xffffff, roughness: 0.9,
17
+ map: canvasTex(512, 512, (g, w, h) => { g.fillStyle = '#7d7268'; g.fillRect(0, 0, w, h); grain(g, w, h, { amount: 22 }); }, { repeat: [8, 8] }),
18
+ }));
19
+ floor.rotation.x = -Math.PI / 2; floor.receiveShadow = true; scene.add(floor);
20
+
21
+ // demo object: a lidded box with a hinge action
22
+ const body = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.5, 0.8), new THREE.MeshStandardMaterial({ color: 0x8a6a4a, roughness: 0.8 }));
23
+ body.position.y = 0.25; body.castShadow = body.receiveShadow = true; scene.add(body);
24
+ const hinge = new THREE.Group(); hinge.position.set(0, 0.5, -0.4); scene.add(hinge);
25
+ const lid = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.06, 0.8), new THREE.MeshStandardMaterial({ color: 0x9a7a58, roughness: 0.7 }));
26
+ lid.position.set(0, 0.03, 0.4); lid.castShadow = true; hinge.add(lid);
27
+ scene.add(contactShadow(2.2, 1.8, { opacity: 0.55 }));
28
+
29
+ return {
30
+ actions: { lid: { label: 'Open the lid', pick: [lid], apply: (t) => { hinge.rotation.x = -t * 1.9; } } },
31
+ update() {},
32
+ };
33
+ }
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright © 2010-2026 three.js authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,216 @@
1
+ import {
2
+ BoxGeometry,
3
+ Vector3
4
+ } from 'three';
5
+
6
+ const _tempNormal = new Vector3();
7
+
8
+ function getUv( faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength ) {
9
+
10
+ const totArcLength = 2 * Math.PI * radius / 4;
11
+
12
+ // length of the planes between the arcs on each axis
13
+ const centerLength = Math.max( sideLength - 2 * radius, 0 );
14
+ const halfArc = Math.PI / 4;
15
+
16
+ // Get the vector projected onto the Y plane
17
+ _tempNormal.copy( normal );
18
+ _tempNormal[ projectionAxis ] = 0;
19
+ _tempNormal.normalize();
20
+
21
+ // total amount of UV space alloted to a single arc
22
+ const arcUvRatio = 0.5 * totArcLength / ( totArcLength + centerLength );
23
+
24
+ // the distance along one arc the point is at
25
+ const arcAngleRatio = 1.0 - ( _tempNormal.angleTo( faceDirVector ) / halfArc );
26
+
27
+ if ( Math.sign( _tempNormal[ uvAxis ] ) === 1 ) {
28
+
29
+ return arcAngleRatio * arcUvRatio;
30
+
31
+ } else {
32
+
33
+ // total amount of UV space alloted to the plane between the arcs
34
+ const lenUv = centerLength / ( totArcLength + centerLength );
35
+ return lenUv + arcUvRatio + arcUvRatio * ( 1.0 - arcAngleRatio );
36
+
37
+ }
38
+
39
+ }
40
+
41
+ /**
42
+ * A special type of box geometry with rounded corners and edges.
43
+ *
44
+ * ```js
45
+ * const geometry = new RoundedBoxGeometry();
46
+ * const material = new THREE.MeshStandardMaterial( { color: 0x00ff00 } );
47
+ * const cube = new THREE.Mesh( geometry, material );
48
+ * scene.add( cube );
49
+ * ```
50
+ *
51
+ * @augments BoxGeometry
52
+ * @three_import import { RoundedBoxGeometry } from 'three/addons/geometries/RoundedBoxGeometry.js';
53
+ */
54
+ class RoundedBoxGeometry extends BoxGeometry {
55
+
56
+ /**
57
+ * Constructs a new rounded box geometry.
58
+ *
59
+ * @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
60
+ * @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
61
+ * @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
62
+ * @param {number} [segments=2] - Number of segments that form the rounded corners.
63
+ * @param {number} [radius=0.1] - The radius of the rounded corners.
64
+ */
65
+ constructor( width = 1, height = 1, depth = 1, segments = 2, radius = 0.1 ) {
66
+
67
+ // calculate total segments needed &
68
+ // ensure it's odd so that we have a plane connecting the rounded corners
69
+ const totalSegments = segments * 2 + 1;
70
+
71
+ // ensure radius isn't bigger than shortest side
72
+ radius = Math.min( width / 2, height / 2, depth / 2, radius );
73
+
74
+ // start with a unit box geometry, its vertices will be modified to form the rounded box
75
+ super( 1, 1, 1, totalSegments, totalSegments, totalSegments );
76
+
77
+ this.type = 'RoundedBoxGeometry';
78
+
79
+ /**
80
+ * Holds the constructor parameters that have been
81
+ * used to generate the geometry. Any modification
82
+ * after instantiation does not change the geometry.
83
+ *
84
+ * @type {Object}
85
+ */
86
+ this.parameters = {
87
+ width: width,
88
+ height: height,
89
+ depth: depth,
90
+ segments: segments,
91
+ radius: radius,
92
+ };
93
+
94
+ // if totalSegments is 1, no rounding is needed - return regular box
95
+ if ( totalSegments === 1 ) return;
96
+
97
+ const geometry2 = this.toNonIndexed();
98
+
99
+ this.index = null;
100
+ this.attributes.position = geometry2.attributes.position;
101
+ this.attributes.normal = geometry2.attributes.normal;
102
+ this.attributes.uv = geometry2.attributes.uv;
103
+
104
+ //
105
+
106
+ const position = new Vector3();
107
+ const normal = new Vector3();
108
+
109
+ const box = new Vector3( width, height, depth ).divideScalar( 2 ).subScalar( radius );
110
+
111
+ const positions = this.attributes.position.array;
112
+ const normals = this.attributes.normal.array;
113
+ const uvs = this.attributes.uv.array;
114
+
115
+ const faceTris = positions.length / 6;
116
+ const faceDirVector = new Vector3();
117
+ const halfSegmentSize = 0.5 / totalSegments;
118
+
119
+ for ( let i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
120
+
121
+ position.fromArray( positions, i );
122
+ normal.copy( position );
123
+ normal.x -= Math.sign( normal.x ) * halfSegmentSize;
124
+ normal.y -= Math.sign( normal.y ) * halfSegmentSize;
125
+ normal.z -= Math.sign( normal.z ) * halfSegmentSize;
126
+ normal.normalize();
127
+
128
+ positions[ i + 0 ] = box.x * Math.sign( position.x ) + normal.x * radius;
129
+ positions[ i + 1 ] = box.y * Math.sign( position.y ) + normal.y * radius;
130
+ positions[ i + 2 ] = box.z * Math.sign( position.z ) + normal.z * radius;
131
+
132
+ normals[ i + 0 ] = normal.x;
133
+ normals[ i + 1 ] = normal.y;
134
+ normals[ i + 2 ] = normal.z;
135
+
136
+ const side = Math.floor( i / faceTris );
137
+
138
+ switch ( side ) {
139
+
140
+ case 0: // right
141
+
142
+ // generate UVs along Z then Y
143
+ faceDirVector.set( 1, 0, 0 );
144
+ uvs[ j + 0 ] = getUv( faceDirVector, normal, 'z', 'y', radius, depth );
145
+ uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height );
146
+ break;
147
+
148
+ case 1: // left
149
+
150
+ // generate UVs along Z then Y
151
+ faceDirVector.set( - 1, 0, 0 );
152
+ uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'y', radius, depth );
153
+ uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height );
154
+ break;
155
+
156
+ case 2: // top
157
+
158
+ // generate UVs along X then Z
159
+ faceDirVector.set( 0, 1, 0 );
160
+ uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width );
161
+ uvs[ j + 1 ] = getUv( faceDirVector, normal, 'z', 'x', radius, depth );
162
+ break;
163
+
164
+ case 3: // bottom
165
+
166
+ // generate UVs along X then Z
167
+ faceDirVector.set( 0, - 1, 0 );
168
+ uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width );
169
+ uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'x', radius, depth );
170
+ break;
171
+
172
+ case 4: // front
173
+
174
+ // generate UVs along X then Y
175
+ faceDirVector.set( 0, 0, 1 );
176
+ uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'y', radius, width );
177
+ uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height );
178
+ break;
179
+
180
+ case 5: // back
181
+
182
+ // generate UVs along X then Y
183
+ faceDirVector.set( 0, 0, - 1 );
184
+ uvs[ j + 0 ] = getUv( faceDirVector, normal, 'x', 'y', radius, width );
185
+ uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height );
186
+ break;
187
+
188
+ }
189
+
190
+ }
191
+
192
+ }
193
+
194
+ /**
195
+ * Factory method for creating an instance of this class from the given
196
+ * JSON object.
197
+ *
198
+ * @param {Object} data - A JSON object representing the serialized geometry.
199
+ * @returns {RoundedBoxGeometry} A new instance.
200
+ */
201
+ static fromJSON( data ) {
202
+
203
+ return new RoundedBoxGeometry(
204
+ data.width,
205
+ data.height,
206
+ data.depth,
207
+ data.segments,
208
+ data.radius
209
+ );
210
+
211
+ }
212
+
213
+
214
+ }
215
+
216
+ export { RoundedBoxGeometry };