@hraness/slopcamera 3.2.4

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 (441) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +60 -0
  3. package/PRIVACY.md +46 -0
  4. package/README.md +311 -0
  5. package/SECURITY.md +21 -0
  6. package/apps/desktop/README.md +966 -0
  7. package/apps/desktop/analysis/protocol.ts +223 -0
  8. package/apps/desktop/application/capability-binding.ts +594 -0
  9. package/apps/desktop/application/context.ts +97 -0
  10. package/apps/desktop/application/creative-iteration.ts +1385 -0
  11. package/apps/desktop/application/default-registry.ts +146 -0
  12. package/apps/desktop/application/directing-contract.ts +218 -0
  13. package/apps/desktop/application/directing-plan.ts +178 -0
  14. package/apps/desktop/application/errors.ts +18 -0
  15. package/apps/desktop/application/gateway-port.ts +867 -0
  16. package/apps/desktop/application/html-overlay-browser-runtime.ts +687 -0
  17. package/apps/desktop/application/html-overlay-integrity.ts +337 -0
  18. package/apps/desktop/application/html-overlay-renderer.ts +45 -0
  19. package/apps/desktop/application/index.ts +13 -0
  20. package/apps/desktop/application/operation-completion-checkpoint.ts +333 -0
  21. package/apps/desktop/application/operation-effects.ts +94 -0
  22. package/apps/desktop/application/operation.ts +224 -0
  23. package/apps/desktop/application/operations/analysis/faces.ts +244 -0
  24. package/apps/desktop/application/operations/analysis/music.ts +248 -0
  25. package/apps/desktop/application/operations/analysis/project-auto-zooms.ts +302 -0
  26. package/apps/desktop/application/operations/analysis/project-inactivity.ts +381 -0
  27. package/apps/desktop/application/operations/analysis/scenes.ts +272 -0
  28. package/apps/desktop/application/operations/analysis/shared.ts +202 -0
  29. package/apps/desktop/application/operations/derive/edit-batch.ts +967 -0
  30. package/apps/desktop/application/operations/derive/follow-faces.ts +454 -0
  31. package/apps/desktop/application/operations/edit/bind-candidate-revision.ts +91 -0
  32. package/apps/desktop/application/operations/edit/create-candidate-revision.ts +377 -0
  33. package/apps/desktop/application/operations/edit/create-revision.ts +255 -0
  34. package/apps/desktop/application/operations/edit/freeze-revision.ts +182 -0
  35. package/apps/desktop/application/operations/gateway/image.ts +41 -0
  36. package/apps/desktop/application/operations/gateway/index.ts +17 -0
  37. package/apps/desktop/application/operations/gateway/shared.ts +122 -0
  38. package/apps/desktop/application/operations/gateway/speech.ts +41 -0
  39. package/apps/desktop/application/operations/gateway/transcription.ts +42 -0
  40. package/apps/desktop/application/operations/gateway/video.ts +41 -0
  41. package/apps/desktop/application/operations/index.ts +31 -0
  42. package/apps/desktop/application/operations/iteration/create-candidate.ts +240 -0
  43. package/apps/desktop/application/operations/iteration/create-matrix.ts +117 -0
  44. package/apps/desktop/application/operations/iteration/select.ts +155 -0
  45. package/apps/desktop/application/operations/iteration/shared.ts +250 -0
  46. package/apps/desktop/application/operations/media/audio-effects.ts +376 -0
  47. package/apps/desktop/application/operations/media/binding.ts +79 -0
  48. package/apps/desktop/application/operations/media/capabilities.ts +112 -0
  49. package/apps/desktop/application/operations/media/color-grade.ts +343 -0
  50. package/apps/desktop/application/operations/media/html-overlay.ts +802 -0
  51. package/apps/desktop/application/operations/media/index.ts +8 -0
  52. package/apps/desktop/application/operations/media/ingest.ts +303 -0
  53. package/apps/desktop/application/operations/media/overlay.ts +729 -0
  54. package/apps/desktop/application/operations/media/shared.ts +845 -0
  55. package/apps/desktop/application/operations/media/transform-platform.ts +120 -0
  56. package/apps/desktop/application/operations/project/commit-edits.ts +2054 -0
  57. package/apps/desktop/application/operations/project/promote-selection.ts +495 -0
  58. package/apps/desktop/application/operations/project/snapshot.ts +95 -0
  59. package/apps/desktop/application/operations/recording/index.ts +5 -0
  60. package/apps/desktop/application/operations/recording/pause.ts +34 -0
  61. package/apps/desktop/application/operations/recording/resume.ts +34 -0
  62. package/apps/desktop/application/operations/recording/shared.ts +199 -0
  63. package/apps/desktop/application/operations/recording/start.ts +169 -0
  64. package/apps/desktop/application/operations/recording/stop.ts +34 -0
  65. package/apps/desktop/application/operations/render/bind-candidate-output.ts +324 -0
  66. package/apps/desktop/application/operations/render/materialize-selection.ts +322 -0
  67. package/apps/desktop/application/operations/render/project-caption-plan.ts +287 -0
  68. package/apps/desktop/application/operations/render/project-plan.ts +939 -0
  69. package/apps/desktop/application/operations/render/project-spatial-receipt.ts +70 -0
  70. package/apps/desktop/application/operations/render/project.ts +1922 -0
  71. package/apps/desktop/application/operations/shared.ts +67 -0
  72. package/apps/desktop/application/operations/slopcamera-portable.ts +1188 -0
  73. package/apps/desktop/application/operations/slopcamera-visuals.ts +784 -0
  74. package/apps/desktop/application/operations/spatial-project.ts +209 -0
  75. package/apps/desktop/application/operations/spatial-render.ts +415 -0
  76. package/apps/desktop/application/operations/spatial-scene.ts +97 -0
  77. package/apps/desktop/application/operations/studio.ts +143 -0
  78. package/apps/desktop/application/output-publication-lease.ts +163 -0
  79. package/apps/desktop/application/project-publication-lease.ts +233 -0
  80. package/apps/desktop/application/project-store.ts +196 -0
  81. package/apps/desktop/application/receipts.ts +533 -0
  82. package/apps/desktop/application/registry.ts +182 -0
  83. package/apps/desktop/application/spatial-assets.ts +675 -0
  84. package/apps/desktop/application/spatial-compositor-cadence.ts +23 -0
  85. package/apps/desktop/application/spatial-project-authority.ts +35 -0
  86. package/apps/desktop/application/spatial-project-lease.ts +126 -0
  87. package/apps/desktop/application/spatial-project-render-preparation.ts +225 -0
  88. package/apps/desktop/application/spatial-project-store.ts +286 -0
  89. package/apps/desktop/application/spatial-render-projection.ts +201 -0
  90. package/apps/desktop/application/spatial-render.ts +677 -0
  91. package/apps/desktop/application/spatial-spz.ts +44 -0
  92. package/apps/desktop/application/spatial-world-import.ts +135 -0
  93. package/apps/desktop/application/spatial-world-provenance.ts +46 -0
  94. package/apps/desktop/application/studio-port.ts +58 -0
  95. package/apps/desktop/application/verified-receipt-reconciliation.ts +1574 -0
  96. package/apps/desktop/capture/protocol.ts +689 -0
  97. package/apps/desktop/cli/analyzer.ts +406 -0
  98. package/apps/desktop/cli/args.ts +3181 -0
  99. package/apps/desktop/cli/asset-ingest.ts +747 -0
  100. package/apps/desktop/cli/atomic-render-effects.ts +210 -0
  101. package/apps/desktop/cli/atomic-render-platform.ts +205 -0
  102. package/apps/desktop/cli/atomic-render.ts +50 -0
  103. package/apps/desktop/cli/audio-analysis.ts +252 -0
  104. package/apps/desktop/cli/bounded-map.ts +39 -0
  105. package/apps/desktop/cli/bundle-service.ts +256 -0
  106. package/apps/desktop/cli/capabilities.ts +212 -0
  107. package/apps/desktop/cli/capture-bundle.ts +1117 -0
  108. package/apps/desktop/cli/command-host-resources.ts +251 -0
  109. package/apps/desktop/cli/commands.ts +6836 -0
  110. package/apps/desktop/cli/directing-blob.ts +291 -0
  111. package/apps/desktop/cli/directing-media.ts +517 -0
  112. package/apps/desktop/cli/directing-quote.ts +89 -0
  113. package/apps/desktop/cli/directing-service.ts +288 -0
  114. package/apps/desktop/cli/emoji-assets.ts +538 -0
  115. package/apps/desktop/cli/errors.ts +29 -0
  116. package/apps/desktop/cli/face-analysis-service.ts +940 -0
  117. package/apps/desktop/cli/filter-script.ts +76 -0
  118. package/apps/desktop/cli/gateway-application-port.ts +1142 -0
  119. package/apps/desktop/cli/gateway-credential.ts +81 -0
  120. package/apps/desktop/cli/gateway-media-artifacts.ts +723 -0
  121. package/apps/desktop/cli/gateway-media-catalog.ts +922 -0
  122. package/apps/desktop/cli/gateway-media-service.ts +3106 -0
  123. package/apps/desktop/cli/gateway-media-signature.ts +122 -0
  124. package/apps/desktop/cli/gateway-provider-options.ts +562 -0
  125. package/apps/desktop/cli/gateway-scene-provider.ts +391 -0
  126. package/apps/desktop/cli/help.ts +501 -0
  127. package/apps/desktop/cli/html-overlay-gpu.ts +97 -0
  128. package/apps/desktop/cli/html-overlay-renderer.ts +2478 -0
  129. package/apps/desktop/cli/io.ts +290 -0
  130. package/apps/desktop/cli/main.ts +123 -0
  131. package/apps/desktop/cli/media-effects-service.ts +885 -0
  132. package/apps/desktop/cli/media-ingest-model.ts +364 -0
  133. package/apps/desktop/cli/media-ingest-platform.ts +227 -0
  134. package/apps/desktop/cli/media-ingest-program.ts +200 -0
  135. package/apps/desktop/cli/media-ingest.ts +30 -0
  136. package/apps/desktop/cli/music-analysis-service.ts +434 -0
  137. package/apps/desktop/cli/mutation-lock.ts +530 -0
  138. package/apps/desktop/cli/native-assets.d.ts +12 -0
  139. package/apps/desktop/cli/native-media-runtime.macos.ts +7 -0
  140. package/apps/desktop/cli/overlay-playback.ts +177 -0
  141. package/apps/desktop/cli/paths.ts +265 -0
  142. package/apps/desktop/cli/portable-surface.ts +242 -0
  143. package/apps/desktop/cli/project-camera-receipt.ts +112 -0
  144. package/apps/desktop/cli/project-face-camera.ts +394 -0
  145. package/apps/desktop/cli/project-inactivity-service.ts +552 -0
  146. package/apps/desktop/cli/project-media-integrity.ts +121 -0
  147. package/apps/desktop/cli/project-renderer.ts +1526 -0
  148. package/apps/desktop/cli/project-service.ts +519 -0
  149. package/apps/desktop/cli/project-state-transaction.ts +520 -0
  150. package/apps/desktop/cli/query-limits.ts +1 -0
  151. package/apps/desktop/cli/recording-controller.ts +1567 -0
  152. package/apps/desktop/cli/recording-daemon.ts +931 -0
  153. package/apps/desktop/cli/recording-ref.ts +56 -0
  154. package/apps/desktop/cli/renamed-environment.ts +6 -0
  155. package/apps/desktop/cli/renderer.ts +1439 -0
  156. package/apps/desktop/cli/run-cli-test-helper.ts +60 -0
  157. package/apps/desktop/cli/scene-analysis-service.ts +879 -0
  158. package/apps/desktop/cli/spatial-compositor-verifier.ts +213 -0
  159. package/apps/desktop/cli/spatial-project-service.ts +90 -0
  160. package/apps/desktop/cli/spatial-scene-service.ts +105 -0
  161. package/apps/desktop/cli/spatial-world-service.ts +39 -0
  162. package/apps/desktop/cli/speech-analysis-service.ts +682 -0
  163. package/apps/desktop/cli/studio-assemble.ts +58 -0
  164. package/apps/desktop/cli/studio-command.ts +60 -0
  165. package/apps/desktop/cli/studio-custody.ts +60 -0
  166. package/apps/desktop/cli/studio-encode.ts +216 -0
  167. package/apps/desktop/cli/studio-exr.ts +52 -0
  168. package/apps/desktop/cli/studio-files.ts +179 -0
  169. package/apps/desktop/cli/studio-output-validation.ts +162 -0
  170. package/apps/desktop/cli/studio-process.ts +145 -0
  171. package/apps/desktop/cli/studio-runtime.ts +77 -0
  172. package/apps/desktop/cli/studio-scaffold.ts +70 -0
  173. package/apps/desktop/cli/studio-service.ts +301 -0
  174. package/apps/desktop/cli/studio-spatial-asset.ts +248 -0
  175. package/apps/desktop/cli/studio-template-names.ts +3 -0
  176. package/apps/desktop/cli/studio-workflow.ts +19 -0
  177. package/apps/desktop/cli/time.ts +25 -0
  178. package/apps/desktop/cli/workflow-code.ts +584 -0
  179. package/apps/desktop/cli/workflow-runs.ts +576 -0
  180. package/apps/desktop/code/advanced.ts +139 -0
  181. package/apps/desktop/code/application-node-planner.ts +1288 -0
  182. package/apps/desktop/code/compiler.ts +329 -0
  183. package/apps/desktop/code/contracts.ts +13 -0
  184. package/apps/desktop/code/creative-recipes.ts +94 -0
  185. package/apps/desktop/code/define-workflow.ts +115 -0
  186. package/apps/desktop/code/editing.ts +284 -0
  187. package/apps/desktop/code/file-candidate-provenance.ts +420 -0
  188. package/apps/desktop/code/file-candidate.ts +69 -0
  189. package/apps/desktop/code/graph-builder.ts +10 -0
  190. package/apps/desktop/code/host-resource-policy.ts +55 -0
  191. package/apps/desktop/code/plan-contracts.ts +159 -0
  192. package/apps/desktop/code/planning.ts +361 -0
  193. package/apps/desktop/code/public.ts +134 -0
  194. package/apps/desktop/code/reference-projection.ts +62 -0
  195. package/apps/desktop/code/run-contracts.ts +466 -0
  196. package/apps/desktop/code/run-store.ts +2478 -0
  197. package/apps/desktop/code/runtime-identity.ts +328 -0
  198. package/apps/desktop/code/scheduler.ts +3067 -0
  199. package/apps/desktop/code/semantic-builder.ts +1436 -0
  200. package/apps/desktop/code/source-bundle.ts +1641 -0
  201. package/apps/desktop/code/source-typecheck.ts +211 -0
  202. package/apps/desktop/code/testing.ts +79 -0
  203. package/apps/desktop/code/worker-client.ts +1675 -0
  204. package/apps/desktop/code/worker-effects.ts +141 -0
  205. package/apps/desktop/code/worker-entry.ts +435 -0
  206. package/apps/desktop/code/worker-lease-guardian.ts +179 -0
  207. package/apps/desktop/code/worker-process-identity.ts +484 -0
  208. package/apps/desktop/code/worker-protocol.ts +211 -0
  209. package/apps/desktop/code/workflow-effects.ts +132 -0
  210. package/apps/desktop/contracts/analysis.ts +949 -0
  211. package/apps/desktop/contracts/edit.ts +576 -0
  212. package/apps/desktop/contracts/index.ts +9 -0
  213. package/apps/desktop/contracts/media-effects.ts +139 -0
  214. package/apps/desktop/contracts/project-render.ts +644 -0
  215. package/apps/desktop/contracts/project.ts +740 -0
  216. package/apps/desktop/contracts/recording.ts +1434 -0
  217. package/apps/desktop/contracts/render.ts +334 -0
  218. package/apps/desktop/contracts/runtime.ts +155 -0
  219. package/apps/desktop/contracts/spatial-compositor.ts +58 -0
  220. package/apps/desktop/contracts/spatial-project.ts +159 -0
  221. package/apps/desktop/contracts/spatial-world.ts +48 -0
  222. package/apps/desktop/contracts/video-effects.ts +120 -0
  223. package/apps/desktop/core/alignment-apply.ts +400 -0
  224. package/apps/desktop/core/audio-alignment.ts +466 -0
  225. package/apps/desktop/core/auto-zoom.ts +209 -0
  226. package/apps/desktop/core/canonical-json.ts +14 -0
  227. package/apps/desktop/core/emoji.ts +210 -0
  228. package/apps/desktop/core/events.ts +409 -0
  229. package/apps/desktop/core/face-framing.ts +533 -0
  230. package/apps/desktop/core/face-tracks.ts +326 -0
  231. package/apps/desktop/core/inactivity.ts +137 -0
  232. package/apps/desktop/core/index.ts +30 -0
  233. package/apps/desktop/core/intervals.ts +123 -0
  234. package/apps/desktop/core/montage.ts +236 -0
  235. package/apps/desktop/core/music-analysis.ts +518 -0
  236. package/apps/desktop/core/plan.ts +244 -0
  237. package/apps/desktop/core/project-auto-zoom.ts +75 -0
  238. package/apps/desktop/core/project-camera-spatial.ts +676 -0
  239. package/apps/desktop/core/project-camera.ts +403 -0
  240. package/apps/desktop/core/project-captions.ts +888 -0
  241. package/apps/desktop/core/project-inactivity.ts +125 -0
  242. package/apps/desktop/core/project-metadata.ts +927 -0
  243. package/apps/desktop/core/project-plan.ts +375 -0
  244. package/apps/desktop/core/project-render-plan.ts +303 -0
  245. package/apps/desktop/core/project-time.ts +469 -0
  246. package/apps/desktop/core/render-plan.ts +442 -0
  247. package/apps/desktop/core/scene-cache.ts +174 -0
  248. package/apps/desktop/core/scene-sampling.ts +448 -0
  249. package/apps/desktop/core/spatial-compositor.ts +22 -0
  250. package/apps/desktop/core/spatial-durability.ts +99 -0
  251. package/apps/desktop/core/spatial-project.ts +169 -0
  252. package/apps/desktop/core/spatial-shot-clock.ts +32 -0
  253. package/apps/desktop/core/speech-analysis.ts +333 -0
  254. package/apps/desktop/core/storage.ts +970 -0
  255. package/apps/desktop/core/time-map.ts +91 -0
  256. package/apps/desktop/core/time.ts +61 -0
  257. package/apps/desktop/core/video-effects.ts +660 -0
  258. package/apps/desktop/dist/cli/NebulaSans-Bold-26se8aek.otf +0 -0
  259. package/apps/desktop/dist/cli/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  260. package/apps/desktop/dist/cli/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  261. package/apps/desktop/dist/cli/NebulaSans-Book-8cenzchw.otf +0 -0
  262. package/apps/desktop/dist/cli/main.js +5086 -0
  263. package/apps/desktop/html-overlay/catalog.ts +171 -0
  264. package/apps/desktop/html-overlay/contracts.ts +372 -0
  265. package/apps/desktop/html-overlay/execution-profile.ts +77 -0
  266. package/apps/desktop/html-overlay/index.ts +98 -0
  267. package/apps/desktop/html-overlay/libraries.ts +263 -0
  268. package/apps/desktop/html-overlay/random.ts +49 -0
  269. package/apps/desktop/html-overlay/runtime.ts +813 -0
  270. package/apps/desktop/html-overlay/scaffolds.ts +792 -0
  271. package/apps/desktop/html-overlay/spark-runtime.ts +88 -0
  272. package/apps/desktop/html-overlay/spatial-splat-runtime.ts +60 -0
  273. package/apps/desktop/html-overlay/spatial.ts +720 -0
  274. package/apps/desktop/studio/assets/README.md +39 -0
  275. package/apps/desktop/studio/assets/contracts.ts +129 -0
  276. package/apps/desktop/studio/assets/network.ts +64 -0
  277. package/apps/desktop/studio/assets/poly-haven.ts +148 -0
  278. package/apps/desktop/studio/drivers/blender_driver.py +466 -0
  279. package/apps/desktop/studio/drivers/cadquery_driver.py +176 -0
  280. package/apps/desktop/studio/education/driver.py +308 -0
  281. package/apps/desktop/studio/education/lesson.py +180 -0
  282. package/apps/desktop/studio/education/toolkit.py +249 -0
  283. package/apps/desktop/workflows/chaptered-demo.ts +48 -0
  284. package/apps/desktop/workflows/creative-iteration.ts +107 -0
  285. package/apps/desktop/workflows/creative-selection.ts +92 -0
  286. package/apps/desktop/workflows/fragments.ts +486 -0
  287. package/apps/desktop/workflows/index.ts +93 -0
  288. package/apps/desktop/workflows/polished-screen-demo.ts +128 -0
  289. package/apps/desktop/workflows/scene-direction.ts +12 -0
  290. package/apps/desktop/workflows/social-variants.ts +75 -0
  291. package/apps/desktop/workflows/talking-head-cleanup.ts +53 -0
  292. package/dist/NebulaSans-Bold-26se8aek.otf +0 -0
  293. package/dist/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  294. package/dist/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  295. package/dist/NebulaSans-Book-8cenzchw.otf +0 -0
  296. package/dist/cli.js +479 -0
  297. package/dist/code/advanced.js +270 -0
  298. package/dist/code/index.js +2240 -0
  299. package/dist/generate.js +24 -0
  300. package/dist/host-resources.js +26 -0
  301. package/dist/index-42zsesc1.js +2257 -0
  302. package/dist/index-7308egqr.js +48 -0
  303. package/dist/index-8txs6fkn.js +712 -0
  304. package/dist/index-mcy8z0br.js +192 -0
  305. package/dist/index-p63wavx0.js +2029 -0
  306. package/dist/index-r7gdhmsp.js +424 -0
  307. package/dist/index-sh6xbav6.js +1219 -0
  308. package/dist/index-z1w83f81.js +4 -0
  309. package/dist/index-z7239b4h.js +2363 -0
  310. package/dist/index-zfeg9hmw.js +2013 -0
  311. package/dist/index.js +241 -0
  312. package/dist/operations.js +29 -0
  313. package/dist/skill-install-dh0ntqba.js +10 -0
  314. package/dist/vectorize/worker.js +142 -0
  315. package/dist/workflow.js +16 -0
  316. package/docs/README.md +38 -0
  317. package/docs/studio.md +215 -0
  318. package/examples/studio/blender/README.md +26 -0
  319. package/examples/studio/blender/character.py +152 -0
  320. package/examples/studio/blender/cloth.py +101 -0
  321. package/examples/studio/blender/color_chart.py +29 -0
  322. package/examples/studio/blender/fluid.py +78 -0
  323. package/examples/studio/blender/import_model.py +74 -0
  324. package/examples/studio/blender/product.py +53 -0
  325. package/examples/studio/blender/shaded_street.py +481 -0
  326. package/examples/studio/blender/studio_scene.py +147 -0
  327. package/examples/studio/cadquery/README.md +13 -0
  328. package/examples/studio/cadquery/bracket.py +36 -0
  329. package/examples/studio/cadquery/import_step.py +12 -0
  330. package/examples/studio/education/README.md +46 -0
  331. package/examples/studio/education/lesson.json +99 -0
  332. package/examples/studio/education/scene.py +7 -0
  333. package/examples/studio/hybrid-scene.ts +96 -0
  334. package/examples/studio/native-workflow.ts +14 -0
  335. package/examples/studio/vgpu/README.md +64 -0
  336. package/examples/studio/vgpu/heat-field.mjs +290 -0
  337. package/package.json +304 -0
  338. package/packages/scene/src/index.ts +1 -0
  339. package/packages/scene/src/scene.ts +215 -0
  340. package/schema/diagram.schema.json +334 -0
  341. package/skills/slopcamera/SKILL.md +45 -0
  342. package/skills/slopcamera/agents/openai.yaml +4 -0
  343. package/skills/slopcamera/references/customization.md +77 -0
  344. package/skills/slopcamera/references/diagrams.md +153 -0
  345. package/skills/slopcamera/references/directed-scenes.md +42 -0
  346. package/skills/slopcamera/references/directing-video.md +18 -0
  347. package/skills/slopcamera/references/educational-video.md +26 -0
  348. package/skills/slopcamera/references/gateway-media.md +134 -0
  349. package/skills/slopcamera/references/install.md +62 -0
  350. package/skills/slopcamera/references/native-studio.md +31 -0
  351. package/skills/slopcamera/references/reference-led-3d.md +140 -0
  352. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-1.jpg +0 -0
  353. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-2.jpg +0 -0
  354. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-1.png +0 -0
  355. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-2.png +0 -0
  356. package/skills/slopcamera/references/rubber-stamp-field-notes.md +144 -0
  357. package/skills/slopcamera/references/vectorization.md +29 -0
  358. package/skills/slopcamera/references/video-projects.md +187 -0
  359. package/skills/slopcamera/references/visual-communication.md +120 -0
  360. package/skills/slopcamera/references/workflows-sdk.md +45 -0
  361. package/skills/slopcamera/scripts/compose-rubber-stamp-field-note.ts +229 -0
  362. package/src/artifacts.ts +106 -0
  363. package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
  364. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
  365. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
  366. package/src/assets/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
  367. package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
  368. package/src/assets/fonts/nebula-sans/PROVENANCE.md +21 -0
  369. package/src/assets.d.ts +9 -0
  370. package/src/cli.ts +601 -0
  371. package/src/cloud-errors.ts +26 -0
  372. package/src/code/advanced.ts +10 -0
  373. package/src/code/boundary.ts +21 -0
  374. package/src/code/canonical-json.ts +129 -0
  375. package/src/code/compiler.ts +953 -0
  376. package/src/code/contracts.ts +576 -0
  377. package/src/code/define-workflow.ts +334 -0
  378. package/src/code/errors.ts +41 -0
  379. package/src/code/graph-builder.ts +945 -0
  380. package/src/code/index.ts +121 -0
  381. package/src/code/json-snapshot.ts +899 -0
  382. package/src/code/json-utf8.ts +88 -0
  383. package/src/code/portable-builder.ts +136 -0
  384. package/src/code/projection.ts +378 -0
  385. package/src/code/public-operations.ts +450 -0
  386. package/src/code/runtime.ts +580 -0
  387. package/src/code/sha256.ts +36 -0
  388. package/src/config.ts +180 -0
  389. package/src/desktop.ts +253 -0
  390. package/src/fs.ts +10 -0
  391. package/src/generate.ts +704 -0
  392. package/src/host-resource-posix.ts +161 -0
  393. package/src/host-resources.ts +1749 -0
  394. package/src/icons.ts +58 -0
  395. package/src/index.ts +200 -0
  396. package/src/label-layout.ts +130 -0
  397. package/src/layout.ts +413 -0
  398. package/src/lint.ts +127 -0
  399. package/src/mcp/boundary.ts +354 -0
  400. package/src/mcp/index.ts +33 -0
  401. package/src/mcp/server.ts +272 -0
  402. package/src/mcp/tools.ts +963 -0
  403. package/src/mcp/types.ts +71 -0
  404. package/src/operations.ts +775 -0
  405. package/src/parse.ts +861 -0
  406. package/src/process-environment.ts +17 -0
  407. package/src/render.ts +437 -0
  408. package/src/skill-install.ts +49 -0
  409. package/src/spatial-scene/authoring.ts +27 -0
  410. package/src/spatial-scene/camera-track.ts +83 -0
  411. package/src/spatial-scene/contracts.ts +277 -0
  412. package/src/spatial-scene/evaluate.ts +145 -0
  413. package/src/spatial-scene/gltf.ts +558 -0
  414. package/src/spatial-scene/identity.ts +260 -0
  415. package/src/spatial-scene/index.ts +10 -0
  416. package/src/spatial-scene/inspect.ts +68 -0
  417. package/src/spatial-scene/math.ts +280 -0
  418. package/src/spatial-scene/patch.ts +131 -0
  419. package/src/spatial-scene/time.ts +53 -0
  420. package/src/studio/contracts.ts +129 -0
  421. package/src/studio/index.ts +2 -0
  422. package/src/studio/plan.ts +156 -0
  423. package/src/studio/shared.ts +41 -0
  424. package/src/theme.ts +68 -0
  425. package/src/tldr.ts +474 -0
  426. package/src/types.ts +212 -0
  427. package/src/vectorize/archive.ts +101 -0
  428. package/src/vectorize/command.ts +797 -0
  429. package/src/vectorize/index.ts +27 -0
  430. package/src/vectorize/limits.ts +61 -0
  431. package/src/vectorize/metrics.ts +351 -0
  432. package/src/vectorize/pixels.ts +323 -0
  433. package/src/vectorize/supervisor.ts +339 -0
  434. package/src/vectorize/svg.ts +188 -0
  435. package/src/vectorize/tool.ts +542 -0
  436. package/src/vectorize/types.ts +113 -0
  437. package/src/vectorize/vectorize.ts +634 -0
  438. package/src/vectorize/worker-protocol.ts +40 -0
  439. package/src/vectorize/worker.ts +209 -0
  440. package/src/version.ts +1 -0
  441. package/src/workflow.ts +409 -0
@@ -0,0 +1,792 @@
1
+ import type { HtmlOverlayInlineDocument } from "./contracts";
2
+ import {
3
+ HtmlOverlayScaffoldKindSchema,
4
+ getHtmlOverlayScaffoldProfile,
5
+ type HtmlOverlayScaffoldKind,
6
+ } from "./catalog";
7
+ import {
8
+ serializeHtmlOverlayImportMap,
9
+ type HtmlOverlayLibrarySpecifier,
10
+ } from "./libraries";
11
+
12
+ export {
13
+ HTML_OVERLAY_SCAFFOLD_KINDS,
14
+ HtmlOverlayScaffoldKindSchema,
15
+ type HtmlOverlayScaffoldKind,
16
+ } from "./catalog";
17
+
18
+ export const HTML_OVERLAY_TRANSPARENT_RESET_CSS = `html,
19
+ body {
20
+ width: 100%;
21
+ height: 100%;
22
+ margin: 0;
23
+ overflow: hidden;
24
+ background: transparent !important;
25
+ }
26
+
27
+ *,
28
+ *::before,
29
+ *::after {
30
+ box-sizing: border-box;
31
+ }`;
32
+
33
+ function documentShell(
34
+ body: string,
35
+ moduleSource: string,
36
+ importMap: string | null,
37
+ ): string {
38
+ const importMapElement = importMap === null
39
+ ? ""
40
+ : `\n <script type="importmap">${importMap}</script>`;
41
+ return `<!doctype html>
42
+ <html lang="en">
43
+ <head>
44
+ <meta charset="utf-8">
45
+ <meta name="viewport" content="width=device-width, initial-scale=1">
46
+ <style>
47
+ ${HTML_OVERLAY_TRANSPARENT_RESET_CSS}
48
+ </style>${importMapElement}
49
+ </head>
50
+ <body>
51
+ ${body}
52
+ <script type="module">
53
+ ${moduleSource}
54
+ </script>
55
+ </body>
56
+ </html>
57
+ `;
58
+ }
59
+
60
+ const PLAIN_SCAFFOLD = documentShell(
61
+ ` <div class="label">Recording</div>
62
+ <style>
63
+ .label {
64
+ position: absolute;
65
+ left: 6%;
66
+ bottom: 8%;
67
+ padding: 0.55em 0.8em;
68
+ border: 1px solid rgb(255 255 255 / 24%);
69
+ border-radius: 0.7em;
70
+ color: white;
71
+ background: rgb(12 16 24 / 82%);
72
+ font: 600 clamp(24px, 4vw, 72px) / 1 system-ui, sans-serif;
73
+ opacity: 0;
74
+ transform-origin: left center;
75
+ }
76
+ </style>`,
77
+ ` const label = document.querySelector(".label");
78
+ SlopcameraOverlay.onFrame(({ progress }) => {
79
+ const reveal = Math.min(1, progress * 8);
80
+ label.style.opacity = String(reveal);
81
+ label.style.transform = \`scale(\${0.94 + reveal * 0.06})\`;
82
+ });`,
83
+ null,
84
+ );
85
+
86
+ const MOTION_SCAFFOLD = documentShell(
87
+ ` <div class="card">Deterministic motion</div>
88
+ <style>
89
+ .card {
90
+ position: absolute;
91
+ left: 8%;
92
+ top: 12%;
93
+ padding: 0.7em 0.9em;
94
+ border-radius: 0.8em;
95
+ color: white;
96
+ background: linear-gradient(135deg, rgb(83 67 255 / 92%), rgb(205 74 255 / 82%));
97
+ box-shadow: 0 1em 3em rgb(14 8 48 / 28%);
98
+ font: 650 clamp(28px, 5vw, 84px) / 1 system-ui, sans-serif;
99
+ opacity: 0;
100
+ }
101
+ </style>`,
102
+ ` import { animate } from "motion";
103
+
104
+ const card = document.querySelector(".card");
105
+ SlopcameraOverlay.trackAnimation(animate(
106
+ card,
107
+ {
108
+ opacity: [0, 1, 1, 0],
109
+ transform: [
110
+ "translateY(40px) scale(.96)",
111
+ "translateY(0) scale(1)",
112
+ "translateY(0) scale(1)",
113
+ "translateY(-24px) scale(.98)",
114
+ ],
115
+ },
116
+ { duration: SlopcameraOverlay.durationMs / 1000, ease: "linear" },
117
+ ));`,
118
+ serializeHtmlOverlayImportMap(["motion"]),
119
+ );
120
+
121
+ const P5_SCAFFOLD = documentShell(
122
+ ` <canvas class="sketch" aria-hidden="true"></canvas>
123
+ <style>
124
+ .sketch {
125
+ display: block;
126
+ width: 100%;
127
+ height: 100%;
128
+ contain: strict;
129
+ }
130
+ </style>`,
131
+ ` import p5 from "p5";
132
+
133
+ // p5 owns drawing, while Slopcamera remains the only clock and entropy source.
134
+ // Keep this P2D starter seek-stable: no hidden frame state, mutable RNG,
135
+ // native frame scheduler, live input, loaders, or cumulative drawing.
136
+ p5.disableFriendlyErrors = true;
137
+ const canvas = document.querySelector(".sketch");
138
+ const particleCount = 48;
139
+ const particles = Object.freeze(Array.from(
140
+ { length: particleCount },
141
+ (_, index) => Object.freeze({
142
+ angle: SlopcameraOverlay.randomFor("p5-angle-" + index) * Math.PI * 2,
143
+ orbit: SlopcameraOverlay.randomFor("p5-orbit-" + index),
144
+ phase: SlopcameraOverlay.randomFor("p5-phase-" + index),
145
+ size: SlopcameraOverlay.randomFor("p5-size-" + index),
146
+ }),
147
+ ));
148
+ let currentFrame = Object.freeze({ progress: 0, timeMs: 0 });
149
+ let sketch = null;
150
+
151
+ const initialization = new Promise((resolve, reject) => {
152
+ try {
153
+ sketch = new p5((p) => {
154
+ let startupDraw = true;
155
+ let startupSettled = false;
156
+ const redraw = p.redraw.bind(p);
157
+ p.redraw = async (...args) => {
158
+ try {
159
+ await redraw(...args);
160
+ if (!startupSettled) {
161
+ startupSettled = true;
162
+ resolve();
163
+ }
164
+ } catch (error) {
165
+ reject(error);
166
+ throw error;
167
+ }
168
+ };
169
+
170
+ p.setup = () => {
171
+ try {
172
+ p.createCanvas(
173
+ SlopcameraOverlay.width,
174
+ SlopcameraOverlay.height,
175
+ p.P2D,
176
+ canvas,
177
+ {
178
+ alpha: true,
179
+ colorSpace: "srgb",
180
+ desynchronized: false,
181
+ },
182
+ );
183
+ p.pixelDensity(devicePixelRatio);
184
+ p.noLoop();
185
+ } catch (error) {
186
+ reject(error);
187
+ throw error;
188
+ }
189
+ };
190
+
191
+ p.draw = () => {
192
+ // p5 performs one mandatory startup draw even after noLoop().
193
+ // The redraw wrapper resolves readiness only after p5 completes
194
+ // this empty draw, including its postdraw and finishDraw work.
195
+ if (startupDraw) {
196
+ startupDraw = false;
197
+ return;
198
+ }
199
+ const { progress, timeMs } = currentFrame;
200
+ const width = SlopcameraOverlay.width;
201
+ const height = SlopcameraOverlay.height;
202
+ const unit = Math.min(width, height);
203
+ const phase = progress * Math.PI * 2;
204
+ p.clear();
205
+ p.resetMatrix();
206
+ p.blendMode(p.BLEND);
207
+ p.noStroke();
208
+
209
+ for (let index = 0; index < particles.length; index += 1) {
210
+ const particle = particles[index];
211
+ const angle = particle.angle
212
+ + phase * (0.18 + particle.phase * 0.42);
213
+ const orbit = unit * (0.14 + particle.orbit * 0.34);
214
+ const wobble = Math.sin(
215
+ timeMs / 700 + particle.phase * Math.PI * 2,
216
+ ) * unit * 0.018;
217
+ const x = width / 2 + Math.cos(angle) * (orbit + wobble);
218
+ const y = height / 2 + Math.sin(angle) * orbit * 0.62;
219
+ const diameter = unit * (0.008 + particle.size * 0.026);
220
+ p.fill(
221
+ 94 + particle.phase * 122,
222
+ 102 + particle.orbit * 92,
223
+ 255,
224
+ 72 + particle.size * 130,
225
+ );
226
+ p.circle(x, y, diameter);
227
+ }
228
+
229
+ const pulse = 0.92 + Math.sin(phase) * 0.08;
230
+ p.fill(105, 82, 255, 72);
231
+ p.circle(width / 2, height / 2, unit * 0.28 * pulse);
232
+ p.fill(104, 232, 255, 185);
233
+ p.circle(width / 2, height / 2, unit * 0.13 * pulse);
234
+ p.fill(255, 255, 255, 255);
235
+ p.circle(width / 2, height / 2, unit * 0.034);
236
+ };
237
+ });
238
+ } catch (error) {
239
+ reject(error);
240
+ }
241
+ });
242
+
243
+ SlopcameraOverlay.ready(initialization);
244
+ SlopcameraOverlay.onFrame(async (frame) => {
245
+ currentFrame = frame;
246
+ await initialization;
247
+ await sketch.redraw();
248
+ });
249
+
250
+ addEventListener("pagehide", () => {
251
+ sketch?.remove();
252
+ }, { once: true });`,
253
+ serializeHtmlOverlayImportMap(["p5"]),
254
+ );
255
+
256
+ const TWO_SCAFFOLD = documentShell(
257
+ ` <canvas class="scene" aria-hidden="true"></canvas>
258
+ <style>
259
+ .scene {
260
+ display: block;
261
+ width: 100%;
262
+ height: 100%;
263
+ contain: strict;
264
+ }
265
+ </style>`,
266
+ ` import Two from "two.js";
267
+
268
+ // Keep Two.js on its explicit WebGL renderer with autostart disabled.
269
+ // Slopcamera remains the only clock and entropy source; this starter uses no
270
+ // textures, loaders, live input, or Two.js animation state.
271
+ let contextError = null;
272
+ let disposing = false;
273
+ const canvas = document.querySelector(".scene");
274
+ const two = new Two({
275
+ alpha: true,
276
+ antialias: false,
277
+ autostart: false,
278
+ domElement: canvas,
279
+ height: SlopcameraOverlay.height,
280
+ overdraw: false,
281
+ premultipliedAlpha: true,
282
+ preserveDrawingBuffer: true,
283
+ ratio: devicePixelRatio,
284
+ type: Two.Types.webgl,
285
+ width: SlopcameraOverlay.width,
286
+ });
287
+ two.renderer.ctx.clearColor(0, 0, 0, 0);
288
+ const stage = new Two.Group();
289
+ two.add(stage);
290
+ const objectCount = 56;
291
+ const colors = [
292
+ "rgba(117, 104, 255, 0.72)",
293
+ "rgba(82, 217, 255, 0.72)",
294
+ "rgba(255, 100, 183, 0.72)",
295
+ "rgba(255, 209, 102, 0.72)",
296
+ ];
297
+ const objects = Object.freeze(Array.from(
298
+ { length: objectCount },
299
+ (_, index) => {
300
+ const angle = SlopcameraOverlay.randomFor("two-angle-" + index)
301
+ * Math.PI * 2;
302
+ const orbit = SlopcameraOverlay.randomFor("two-orbit-" + index);
303
+ const phase = SlopcameraOverlay.randomFor("two-phase-" + index);
304
+ const size = SlopcameraOverlay.randomFor("two-size-" + index);
305
+ const shape = new Two.Circle(0, 0, 4 + size * 18, 24);
306
+ shape.fill = colors[index % colors.length];
307
+ shape.noStroke();
308
+ stage.add(shape);
309
+ return Object.freeze({ angle, orbit, phase, shape, size });
310
+ },
311
+ ));
312
+ const core = new Two.Circle(0, 0, 18, 32);
313
+ core.fill = "rgba(255, 255, 255, 1)";
314
+ core.noStroke();
315
+ stage.add(core);
316
+
317
+ const handleContextLoss = (event) => {
318
+ event.preventDefault();
319
+ if (!disposing) {
320
+ contextError = new Error("The Two.js rendering context was lost.");
321
+ throw contextError;
322
+ }
323
+ };
324
+ canvas.addEventListener("webglcontextlost", handleContextLoss);
325
+
326
+ SlopcameraOverlay.onFrame(({ progress, timeMs }) => {
327
+ if (contextError !== null) throw contextError;
328
+ const width = SlopcameraOverlay.width;
329
+ const height = SlopcameraOverlay.height;
330
+ const unit = Math.min(width, height);
331
+ const absolutePhase = progress * Math.PI * 2;
332
+ for (const object of objects) {
333
+ const angle = object.angle
334
+ + absolutePhase * (0.16 + object.phase * 0.44);
335
+ const orbit = unit * (0.13 + object.orbit * 0.36);
336
+ const wobble = Math.sin(
337
+ timeMs / 760 + object.phase * Math.PI * 2,
338
+ ) * unit * 0.016;
339
+ object.shape.translation.set(
340
+ width / 2 + Math.cos(angle) * (orbit + wobble),
341
+ height / 2 + Math.sin(angle) * orbit * 0.58,
342
+ );
343
+ object.shape.rotation = angle + Math.PI / 2;
344
+ }
345
+ core.translation.set(width / 2, height / 2);
346
+ two.render();
347
+ });
348
+
349
+ addEventListener("pagehide", () => {
350
+ disposing = true;
351
+ canvas.removeEventListener("webglcontextlost", handleContextLoss);
352
+ two.pause();
353
+ two.release();
354
+ two.clear();
355
+ two.unbind();
356
+ two.renderer.unbind();
357
+ const index = Two.Instances.indexOf(two);
358
+ if (index >= 0) Two.Instances.splice(index, 1);
359
+ two.renderer.ctx.getExtension("WEBGL_lose_context")?.loseContext();
360
+ }, { once: true });`,
361
+ serializeHtmlOverlayImportMap(["two.js"]),
362
+ );
363
+
364
+ const PAPER_SCAFFOLD = documentShell(
365
+ ` <div class="shader" aria-hidden="true"></div>
366
+ <style>
367
+ .shader {
368
+ position: absolute;
369
+ inset: 10%;
370
+ overflow: hidden;
371
+ border-radius: min(8vw, 96px);
372
+ filter: drop-shadow(0 24px 64px rgb(21 9 60 / 25%));
373
+ }
374
+ </style>`,
375
+ ` import {
376
+ ShaderFitOptions,
377
+ ShaderMount,
378
+ getShaderColorFromString,
379
+ meshGradientFragmentShader,
380
+ } from "@paper-design/shaders";
381
+
382
+ const colors = ["#6d5dfc", "#ff67c7", "#56e0d3", "#ffd166"];
383
+ const shader = new ShaderMount(
384
+ document.querySelector(".shader"),
385
+ meshGradientFragmentShader,
386
+ {
387
+ u_colors: colors.map(getShaderColorFromString),
388
+ u_colorsCount: colors.length,
389
+ u_distortion: 0.8,
390
+ u_fit: ShaderFitOptions.cover,
391
+ u_grainMixer: 0.16,
392
+ u_grainOverlay: 0.08,
393
+ u_offsetX: 0,
394
+ u_offsetY: 0,
395
+ u_originX: 0.5,
396
+ u_originY: 0.5,
397
+ u_rotation: 0,
398
+ u_scale: 1,
399
+ u_swirl: 0.35,
400
+ u_worldHeight: SlopcameraOverlay.height,
401
+ u_worldWidth: SlopcameraOverlay.width,
402
+ },
403
+ { alpha: true, premultipliedAlpha: false },
404
+ 0,
405
+ );
406
+
407
+ SlopcameraOverlay.onFrame(({ timeMs }) => shader.setFrame(timeMs));`,
408
+ serializeHtmlOverlayImportMap(["@paper-design/shaders"]),
409
+ );
410
+
411
+ const THREE_SCAFFOLD = documentShell(
412
+ ` <canvas class="scene" aria-hidden="true"></canvas>
413
+ <style>
414
+ .scene {
415
+ display: block;
416
+ width: 100%;
417
+ height: 100%;
418
+ contain: strict;
419
+ }
420
+ </style>`,
421
+ ` import * as THREE from "three";
422
+
423
+ // Keep this scene seek-stable: derive motion from progress/timeMs and use
424
+ // SlopcameraOverlay.randomFor(key), never requestAnimationFrame or mutable RNG.
425
+ const MAX_DRAW_CALLS = 64;
426
+ const MAX_TRIANGLES = 200_000;
427
+ const canvas = document.querySelector(".scene");
428
+ const renderer = new THREE.WebGLRenderer({
429
+ alpha: true,
430
+ antialias: true,
431
+ canvas,
432
+ powerPreference: "high-performance",
433
+ premultipliedAlpha: false,
434
+ });
435
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
436
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
437
+ renderer.toneMappingExposure = 1;
438
+ renderer.shadowMap.enabled = false;
439
+ // The authoring canvas owns preview/final supersampling. Use 1x for
440
+ // iteration and raise deviceScaleFactor only for a selected final render.
441
+ renderer.setPixelRatio(devicePixelRatio);
442
+ renderer.setSize(SlopcameraOverlay.width, SlopcameraOverlay.height, false);
443
+ renderer.setClearColor(0x000000, 0);
444
+
445
+ const scene = new THREE.Scene();
446
+ const camera = new THREE.PerspectiveCamera(
447
+ 42,
448
+ SlopcameraOverlay.width / SlopcameraOverlay.height,
449
+ 0.1,
450
+ 100,
451
+ );
452
+
453
+ const disposable = new Set();
454
+ const track = (resource) => {
455
+ disposable.add(resource);
456
+ return resource;
457
+ };
458
+
459
+ // Replace only this function when generating a subject. Reuse geometry
460
+ // and materials, prefer instancing for repeated forms, and track every
461
+ // GPU resource created outside this starter.
462
+ function createSubject() {
463
+ const subject = new THREE.Group();
464
+ const geometry = track(new THREE.IcosahedronGeometry(0.72, 1));
465
+ const material = track(new THREE.MeshStandardMaterial({
466
+ color: 0x7c6cff,
467
+ flatShading: true,
468
+ metalness: 0.18,
469
+ roughness: 0.42,
470
+ }));
471
+ for (const [x, y, z, scale] of [
472
+ [-0.72, 0, 0, 1],
473
+ [0.72, 0, 0, 0.82],
474
+ [0, 0.72, -0.08, 0.68],
475
+ [0, -0.72, 0.08, 0.58],
476
+ ]) {
477
+ const part = new THREE.Mesh(geometry, material);
478
+ part.position.set(x, y, z);
479
+ part.scale.setScalar(scale);
480
+ subject.add(part);
481
+ }
482
+ return subject;
483
+ }
484
+
485
+ const subject = createSubject();
486
+ scene.add(subject);
487
+ scene.add(new THREE.HemisphereLight(0xffffff, 0x20243a, 2.1));
488
+ const keyLight = new THREE.DirectionalLight(0xffffff, 3.2);
489
+ keyLight.position.set(3, 5, 4);
490
+ scene.add(keyLight);
491
+
492
+ const bounds = new THREE.Box3().setFromObject(subject);
493
+ const sphere = bounds.getBoundingSphere(new THREE.Sphere());
494
+ const verticalHalfFov = THREE.MathUtils.degToRad(camera.fov * 0.5);
495
+ const horizontalHalfFov = Math.atan(
496
+ Math.tan(verticalHalfFov) * camera.aspect,
497
+ );
498
+ const fitHalfFov = Math.min(verticalHalfFov, horizontalHalfFov);
499
+ const framingDistance = Math.max(
500
+ 0.01,
501
+ (sphere.radius / Math.sin(fitHalfFov)) * 1.25,
502
+ );
503
+ camera.near = Math.max(0.01, framingDistance / 100);
504
+ camera.far = framingDistance * 20;
505
+ camera.updateProjectionMatrix();
506
+ const cameraDirection = new THREE.Vector3(0.42, 0.24, 1).normalize();
507
+ camera.position.copy(sphere.center).addScaledVector(
508
+ cameraDirection,
509
+ framingDistance,
510
+ );
511
+ camera.lookAt(sphere.center);
512
+
513
+ const explodeParts = subject.children.map((part) => {
514
+ const home = part.position.clone();
515
+ const direction = home.clone();
516
+ if (direction.lengthSq() === 0) direction.set(0, 1, 0);
517
+ direction.normalize();
518
+ return { direction, home, part };
519
+ });
520
+ const numberParameter = (name, fallback, minimum, maximum) => {
521
+ const value = SlopcameraOverlay.parameters[name];
522
+ return typeof value === "number" && Number.isFinite(value)
523
+ ? THREE.MathUtils.clamp(value, minimum, maximum)
524
+ : fallback;
525
+ };
526
+ const explodeDistance = numberParameter("explode", 0.45, 0, 4);
527
+ const orbitTurns = numberParameter("orbitTurns", 1, -8, 8);
528
+ const zoom = numberParameter("zoom", 1, 0.25, 4);
529
+
530
+ canvas.addEventListener("webglcontextlost", (event) => {
531
+ event.preventDefault();
532
+ throw new Error("The Three.js rendering context was lost.");
533
+ });
534
+ SlopcameraOverlay.ready(renderer.compileAsync(scene, camera));
535
+
536
+ SlopcameraOverlay.onFrame(({ progress }) => {
537
+ const phase = progress * Math.PI * 2;
538
+ subject.rotation.set(
539
+ Math.sin(phase) * 0.08,
540
+ phase * orbitTurns,
541
+ Math.cos(phase) * 0.04,
542
+ );
543
+ const explode = Math.sin(progress * Math.PI) ** 2 * explodeDistance;
544
+ for (const { direction, home, part } of explodeParts) {
545
+ part.position.copy(home).addScaledVector(direction, explode);
546
+ }
547
+ camera.position.copy(sphere.center).addScaledVector(
548
+ cameraDirection,
549
+ framingDistance / zoom,
550
+ );
551
+ camera.lookAt(sphere.center);
552
+ renderer.render(scene, camera);
553
+ if (
554
+ renderer.info.render.calls > MAX_DRAW_CALLS
555
+ || renderer.info.render.triangles > MAX_TRIANGLES
556
+ ) {
557
+ throw new Error(
558
+ "Three.js render budget exceeded: "
559
+ + renderer.info.render.calls
560
+ + " calls, "
561
+ + renderer.info.render.triangles
562
+ + " triangles.",
563
+ );
564
+ }
565
+ });
566
+
567
+ addEventListener("pagehide", () => {
568
+ for (const resource of disposable) resource.dispose();
569
+ renderer.dispose();
570
+ renderer.forceContextLoss();
571
+ }, { once: true });`,
572
+ serializeHtmlOverlayImportMap(["three"]),
573
+ );
574
+
575
+ const VGPU_SCAFFOLD = documentShell(
576
+ ` <canvas class="effect" aria-hidden="true"></canvas>
577
+ <style>
578
+ .effect {
579
+ display: block;
580
+ width: 100%;
581
+ height: 100%;
582
+ contain: strict;
583
+ }
584
+ </style>`,
585
+ ` import { effect, frame, init, surface, target } from "vgpu";
586
+
587
+ // Keep this starter seek-stable: derive every value from the absolute
588
+ // Slopcamera frame and submit one bounded fullscreen pass per output frame.
589
+ const canvas = document.querySelector(".effect");
590
+ const shaderSource = \`
591
+ struct Params {
592
+ time: f32,
593
+ resolution: vec2f,
594
+ intensity: f32,
595
+ }
596
+
597
+ @group(0) @binding(0) var<uniform> params: Params;
598
+
599
+ fn palette(value: f32) -> vec3f {
600
+ let phase = vec3f(0.08, 0.31, 0.58) + value;
601
+ return vec3f(0.55) + 0.45 * cos(6.2831853 * phase);
602
+ }
603
+
604
+ @fragment fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
605
+ let safeHeight = max(params.resolution.y, 1.0);
606
+ let aspect = params.resolution.x / safeHeight;
607
+ let point = (uv - vec2f(0.5)) * vec2f(aspect, 1.0);
608
+ let wave = sin(point.x * 5.0 + params.time * 1.4) * 0.08
609
+ + sin(point.x * 11.0 - params.time * 0.9) * 0.035;
610
+ let band = exp(-abs(point.y - wave) * 18.0);
611
+ let halo = exp(-length(point) * 3.4);
612
+ let alpha = clamp(
613
+ (band * 0.72 + halo * 0.22) * params.intensity,
614
+ 0.0,
615
+ 0.86,
616
+ );
617
+ let color = palette(point.x * 0.16 + params.time * 0.035);
618
+ return vec4f(color * alpha, alpha);
619
+ }
620
+ \`;
621
+
622
+ const numberParameter = (name, fallback, minimum, maximum) => {
623
+ const value = SlopcameraOverlay.parameters[name];
624
+ return typeof value === "number" && Number.isFinite(value)
625
+ ? Math.min(maximum, Math.max(minimum, value))
626
+ : fallback;
627
+ };
628
+ const intensity = numberParameter("intensity", 1, 0, 2);
629
+ const speed = numberParameter("speed", 1, -8, 8);
630
+ const initialization = (async () => {
631
+ if (navigator.gpu === undefined) {
632
+ throw new Error("The vgpu scaffold requires WebGPU in the selected browser runtime.");
633
+ }
634
+ const gpu = await init({ powerPreference: "high-performance" });
635
+ let asynchronousError = null;
636
+ const releaseErrorListener = gpu.onError((error) => {
637
+ asynchronousError ??= error;
638
+ });
639
+ void gpu.gpu.lost.then(() => {
640
+ if (!gpu.disposed) {
641
+ asynchronousError ??= new Error(
642
+ "The WebGPU device was lost during the HTML overlay render.",
643
+ );
644
+ }
645
+ });
646
+ try {
647
+ const output = surface(gpu, canvas, {
648
+ alphaMode: "premultiplied",
649
+ autoResize: false,
650
+ clearColor: [0, 0, 0, 0],
651
+ dpr: devicePixelRatio,
652
+ });
653
+ const shader = effect(gpu, shaderSource, {
654
+ set: {
655
+ params: {
656
+ intensity,
657
+ resolution: output.size,
658
+ time: 0,
659
+ },
660
+ },
661
+ });
662
+ const pipelineTarget = target(gpu, {
663
+ format: output.format,
664
+ size: [1, 1],
665
+ });
666
+ try {
667
+ await shader.compile(pipelineTarget);
668
+ } finally {
669
+ pipelineTarget.destroy();
670
+ }
671
+ await gpu.settled();
672
+ if (asynchronousError !== null) throw asynchronousError;
673
+ return {
674
+ dispose() {
675
+ releaseErrorListener();
676
+ gpu.dispose();
677
+ },
678
+ gpu,
679
+ output,
680
+ shader,
681
+ takeError() {
682
+ const error = asynchronousError;
683
+ asynchronousError = null;
684
+ return error;
685
+ },
686
+ };
687
+ } catch (error) {
688
+ try {
689
+ releaseErrorListener();
690
+ gpu.dispose();
691
+ } catch {
692
+ // Preserve the initialization failure if cleanup also fails.
693
+ }
694
+ throw error;
695
+ }
696
+ })();
697
+
698
+ SlopcameraOverlay.ready(initialization);
699
+ SlopcameraOverlay.onFrame(async ({ timeMs }) => {
700
+ const state = await initialization;
701
+ state.shader.set({
702
+ params: {
703
+ intensity,
704
+ resolution: state.output.size,
705
+ time: timeMs * speed / 1000,
706
+ },
707
+ });
708
+ const submitted = frame(state.gpu, (currentFrame) => {
709
+ currentFrame.pass(
710
+ { clear: [0, 0, 0, 0], target: state.output },
711
+ state.shader,
712
+ );
713
+ });
714
+ await submitted.done;
715
+ await state.gpu.settled();
716
+ const error = state.takeError();
717
+ if (error !== null) throw error;
718
+ });
719
+
720
+ addEventListener("pagehide", () => {
721
+ void initialization.then((state) => state.dispose()).catch(() => undefined);
722
+ }, { once: true });`,
723
+ serializeHtmlOverlayImportMap(["vgpu"]),
724
+ );
725
+
726
+ const SCAFFOLDS = Object.freeze({
727
+ motion: MOTION_SCAFFOLD,
728
+ p5: P5_SCAFFOLD,
729
+ "paper-shaders": PAPER_SCAFFOLD,
730
+ two: TWO_SCAFFOLD,
731
+ plain: PLAIN_SCAFFOLD,
732
+ three: THREE_SCAFFOLD,
733
+ vgpu: VGPU_SCAFFOLD,
734
+ }) satisfies Readonly<Record<HtmlOverlayScaffoldKind, string>>;
735
+
736
+ export interface HtmlOverlayScaffoldInput {
737
+ readonly document: HtmlOverlayInlineDocument;
738
+ /** Exact browser libraries required by the generated document. */
739
+ readonly libraries: HtmlOverlayLibrarySpecifier[];
740
+ }
741
+
742
+ export const THREE_REFERENCE_RESOURCE_NAME = "reference-image" as const;
743
+ export const THREE_REFERENCE_RESOURCE_URL_PATH =
744
+ "assets/reference-image" as const;
745
+
746
+ export interface ThreeReferenceScaffoldInput<TArtifact, TMediaType>
747
+ extends HtmlOverlayScaffoldInput {
748
+ readonly resources: readonly [{
749
+ readonly artifact: TArtifact;
750
+ readonly mediaType: TMediaType;
751
+ readonly name: typeof THREE_REFERENCE_RESOURCE_NAME;
752
+ readonly urlPath: typeof THREE_REFERENCE_RESOURCE_URL_PATH;
753
+ }];
754
+ }
755
+
756
+ export function createHtmlOverlayScaffoldInput(
757
+ kind: HtmlOverlayScaffoldKind,
758
+ ): HtmlOverlayScaffoldInput {
759
+ const parsed = HtmlOverlayScaffoldKindSchema.parse(kind);
760
+ const libraries: HtmlOverlayLibrarySpecifier[] = [
761
+ ...getHtmlOverlayScaffoldProfile(parsed).libraries,
762
+ ];
763
+ Object.freeze(libraries);
764
+ return Object.freeze({
765
+ document: Object.freeze({ html: SCAFFOLDS[parsed] }),
766
+ libraries,
767
+ });
768
+ }
769
+
770
+ export function createHtmlOverlayScaffold(kind: HtmlOverlayScaffoldKind): string {
771
+ return SCAFFOLDS[HtmlOverlayScaffoldKindSchema.parse(kind)];
772
+ }
773
+
774
+ /**
775
+ * Binds one exact image to the general Three.js starter as code-generation
776
+ * provenance. The author edits the returned document's createSubject()
777
+ * function after inspecting that image; Slopcamera never evaluates model text.
778
+ */
779
+ export function createThreeReferenceScaffoldInput<TArtifact, TMediaType>(
780
+ artifact: TArtifact,
781
+ mediaType: TMediaType,
782
+ ): ThreeReferenceScaffoldInput<TArtifact, TMediaType> {
783
+ const scaffold = createHtmlOverlayScaffoldInput("three");
784
+ const resource = Object.freeze({
785
+ artifact,
786
+ mediaType,
787
+ name: THREE_REFERENCE_RESOURCE_NAME,
788
+ urlPath: THREE_REFERENCE_RESOURCE_URL_PATH,
789
+ });
790
+ const resources = Object.freeze([resource] as const);
791
+ return Object.freeze({ ...scaffold, resources });
792
+ }