cozyclay 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +40 -113
  4. package/bin/agent/agent-runner.mjs +9 -10
  5. package/bin/agent/cliproxy-provider.mjs +135 -0
  6. package/bin/agent/credential-store.mjs +30 -7
  7. package/bin/agent/pi-tools.mjs +4 -1
  8. package/bin/agent/provider-keys.mjs +32 -0
  9. package/bin/agent/provider-login.mjs +110 -0
  10. package/bin/agent/provider-routes.mjs +99 -0
  11. package/bin/agent/providers.mjs +19 -97
  12. package/bin/agent/script-tool.mjs +17 -4
  13. package/bin/agent/studio-motion-reference.mjs +23 -0
  14. package/bin/agent/studio-prompt.mjs +1 -1
  15. package/bin/agent/studio-rebase-text.mjs +32 -0
  16. package/bin/agent/studio-rebase.mjs +26 -39
  17. package/bin/agent/studio-tools.mjs +9 -28
  18. package/bin/agent/tool-arguments.mjs +49 -0
  19. package/bin/agent/turn-frames.mjs +66 -0
  20. package/bin/codex-auth.mjs +9 -2
  21. package/bin/cozyclay.mjs +10 -116
  22. package/bin/live/cli.mjs +3 -3
  23. package/bin/mcp-runtime.mjs +2 -12
  24. package/bin/package-signature.mjs +0 -4
  25. package/dist/app/index.html +7 -6
  26. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  27. package/dist/assets/analytics-C9sUnndd.js +1 -0
  28. package/dist/assets/app-CCh--1Hc.js +5087 -0
  29. package/dist/assets/app-f-fkV5uP.css +1 -0
  30. package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
  31. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  32. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-ChUvB_zL.js → landing-DjHD8u7k.js} +1 -1
  34. package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
  35. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  36. package/dist/assets/workflow-C4yKH1p4.js +179 -0
  37. package/dist/cozyclay-package.json +1 -1
  38. package/dist/index.html +3 -3
  39. package/dist/sw.js +3 -6
  40. package/dist/workflow/index.html +5 -4
  41. package/mcp/LIVE-PROTOCOL.md +7 -47
  42. package/mcp/README.md +16 -26
  43. package/mcp/live-hub.mjs +6 -10
  44. package/mcp/package.json +1 -3
  45. package/mcp/tool-handlers.mjs +4 -168
  46. package/package.json +3 -22
  47. package/src/App.jsx +150 -2624
  48. package/src/agent-progress.js +79 -0
  49. package/src/agent-turn-mark.js +30 -0
  50. package/src/analytics.js +1 -19
  51. package/src/app-context.js +5 -0
  52. package/src/app-stage.jsx +2 -34
  53. package/src/asset-pane.jsx +6 -5
  54. package/src/camera-block.js +21 -0
  55. package/src/camera-direction.js +120 -0
  56. package/src/character-kind.js +3 -9
  57. package/src/command-bus.js +8 -6
  58. package/src/commands/cast.js +5 -34
  59. package/src/commands/elements/character.js +1 -1
  60. package/src/commands/elements/motion.js +1 -6
  61. package/src/commands/elements/object.js +6 -2
  62. package/src/commands/elements/shot.js +4 -1
  63. package/src/commands/elements.js +38 -14
  64. package/src/commands/index.js +3 -1
  65. package/src/commands/kits.js +37 -0
  66. package/src/commands/motion-timing.js +57 -0
  67. package/src/commands/motion.js +9 -152
  68. package/src/commands/motion3-compile.js +65 -0
  69. package/src/commands/motion3.js +207 -0
  70. package/src/commands/objects.js +6 -4
  71. package/src/commands/shot.js +49 -11
  72. package/src/commands/stage.js +14 -1
  73. package/src/commands/view.js +4 -1
  74. package/src/document-mirrors.js +42 -0
  75. package/src/document-store.js +4 -0
  76. package/src/domains/cast.js +19 -194
  77. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  78. package/src/domains/motion/take-source.js +51 -0
  79. package/src/domains/motion.js +60 -1838
  80. package/src/domains/scenes.js +12 -55
  81. package/src/domains/shots.js +2 -2
  82. package/src/domains/stage.js +4 -2
  83. package/src/draft-ghost.js +46 -0
  84. package/src/draft-ghost.jsx +129 -0
  85. package/src/dualview.jsx +4 -3
  86. package/src/effects/EffectsLayer.jsx +112 -0
  87. package/src/effects/effect-meshes.js +232 -0
  88. package/src/effects/effect-record.js +103 -0
  89. package/src/effects/emitter.js +59 -0
  90. package/src/effects/simulate.js +261 -0
  91. package/src/effects/state.js +59 -0
  92. package/src/execution-telemetry.js +2 -3
  93. package/src/first-success-guide.jsx +5 -5
  94. package/src/ghost-set.js +257 -0
  95. package/src/held-object-edit.jsx +113 -0
  96. package/src/held-object-pose.js +175 -0
  97. package/src/hierarchy-model.js +1 -1
  98. package/src/hierarchy-panel.jsx +1 -1
  99. package/src/imported-mesh.jsx +103 -0
  100. package/src/kits/held.js +84 -0
  101. package/src/kits/index.js +70 -0
  102. package/src/kits/smoking.js +57 -0
  103. package/src/light-blockers.js +93 -0
  104. package/src/motion/beat-board-model.js +84 -0
  105. package/src/motion/beat-board.css +124 -0
  106. package/src/motion/beat-board.jsx +59 -0
  107. package/src/motion/center-of-mass.js +66 -0
  108. package/src/motion/fix-collisions.js +850 -0
  109. package/src/motion/physics-review.js +118 -0
  110. package/src/{ardy → motion}/physics-support.js +1 -76
  111. package/src/motion/rig-snapshot.js +22 -0
  112. package/src/motion/take-segments.jsx +140 -0
  113. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  114. package/src/{ardy → motion}/timeline.css +1 -2
  115. package/src/{ardy → motion}/timeline.jsx +42 -413
  116. package/src/motion/waypoints.js +76 -0
  117. package/src/motion3/beats.js +83 -0
  118. package/src/motion3/body.js +158 -0
  119. package/src/motion3/bones.js +47 -0
  120. package/src/motion3/carried.js +47 -0
  121. package/src/motion3/compile-job.js +75 -0
  122. package/src/motion3/compile-worker.js +10 -0
  123. package/src/motion3/compiler/anchors.js +105 -0
  124. package/src/motion3/compiler/arm-orient.js +128 -0
  125. package/src/motion3/compiler/channels.js +125 -0
  126. package/src/motion3/compiler/compile.js +205 -0
  127. package/src/motion3/compiler/gait-rhythm.js +97 -0
  128. package/src/motion3/compiler/grip.js +171 -0
  129. package/src/motion3/compiler/head-steady.js +48 -0
  130. package/src/motion3/compiler/hold.js +134 -0
  131. package/src/motion3/compiler/idle.js +113 -0
  132. package/src/motion3/compiler/limbs.js +170 -0
  133. package/src/motion3/compiler/math.js +72 -0
  134. package/src/motion3/compiler/pose.js +162 -0
  135. package/src/motion3/compiler/quat.js +49 -0
  136. package/src/motion3/compiler/skeleton.js +74 -0
  137. package/src/motion3/compiler/validate-common.js +32 -0
  138. package/src/motion3/compiler/validate-goals.js +118 -0
  139. package/src/motion3/compiler/validate-objects.js +143 -0
  140. package/src/motion3/compiler/validate-parts.js +116 -0
  141. package/src/motion3/compiler/validate.js +122 -0
  142. package/src/motion3/compiler/vocab.js +73 -0
  143. package/src/motion3/compiler/walk-pelvis.js +275 -0
  144. package/src/motion3/compiler/walk.js +207 -0
  145. package/src/motion3/compiler/wrist-clamp.js +32 -0
  146. package/src/motion3/delta.js +47 -0
  147. package/src/motion3/describe.js +174 -0
  148. package/src/motion3/docs.js +27 -0
  149. package/src/motion3/edit-carry.js +21 -0
  150. package/src/motion3/fix/ease.js +16 -0
  151. package/src/motion3/fix/ground.js +37 -0
  152. package/src/motion3/fix/index.js +52 -0
  153. package/src/motion3/fix/push.js +71 -0
  154. package/src/motion3/fix/reach.js +46 -0
  155. package/src/motion3/fix/retime.js +79 -0
  156. package/src/motion3/fix/self.js +211 -0
  157. package/src/motion3/fix/slide.js +70 -0
  158. package/src/motion3/fix/turn.js +51 -0
  159. package/src/motion3/follow.js +39 -0
  160. package/src/motion3/free-motion.js +173 -0
  161. package/src/motion3/grip-choice.js +130 -0
  162. package/src/motion3/hold-plan.js +157 -0
  163. package/src/motion3/json-patch.js +77 -0
  164. package/src/motion3/key-aim.js +105 -0
  165. package/src/motion3/key-edit.js +82 -0
  166. package/src/motion3/lenient.js +127 -0
  167. package/src/motion3/object-keys.js +236 -0
  168. package/src/motion3/object-pose.js +182 -0
  169. package/src/motion3/object-tracks.js +12 -0
  170. package/src/motion3/pipeline.js +102 -0
  171. package/src/motion3/playback.js +51 -0
  172. package/src/motion3/probes.js +91 -0
  173. package/src/motion3/qa/body-checks.js +34 -0
  174. package/src/motion3/qa/check-names.js +14 -0
  175. package/src/motion3/qa/checks.js +121 -0
  176. package/src/motion3/qa/contact-checks.js +51 -0
  177. package/src/motion3/qa/explain.js +80 -0
  178. package/src/motion3/qa/fmt.js +5 -0
  179. package/src/motion3/qa/foot-checks.js +72 -0
  180. package/src/motion3/qa/geometry.js +77 -0
  181. package/src/motion3/qa/goals.js +191 -0
  182. package/src/motion3/qa/ground.js +60 -0
  183. package/src/motion3/qa/hints-contact.js +179 -0
  184. package/src/motion3/qa/hints-goal.js +160 -0
  185. package/src/motion3/qa/hints-knee.js +24 -0
  186. package/src/motion3/qa/hints-motion.js +209 -0
  187. package/src/motion3/qa/hints-object.js +91 -0
  188. package/src/motion3/qa/index.js +42 -0
  189. package/src/motion3/qa/key-checks.js +82 -0
  190. package/src/motion3/qa/near.js +96 -0
  191. package/src/motion3/qa/object-checks.js +135 -0
  192. package/src/motion3/qa/patch.js +161 -0
  193. package/src/motion3/qa/severity.js +38 -0
  194. package/src/motion3/qa/spec-checks.js +65 -0
  195. package/src/motion3/qa/style.js +218 -0
  196. package/src/motion3/qa/wrist-checks.js +69 -0
  197. package/src/motion3/qa/wrist-obs.js +60 -0
  198. package/src/motion3/refs.js +120 -0
  199. package/src/motion3/repair-tune.js +121 -0
  200. package/src/motion3/repair.js +83 -0
  201. package/src/motion3/report.js +67 -0
  202. package/src/motion3/rigs/index.js +14 -0
  203. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  204. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  205. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  207. package/src/motion3/scene.js +60 -0
  208. package/src/motion3/schema/brief.js +89 -0
  209. package/src/motion3/schema/fields.js +44 -0
  210. package/src/motion3/schema/spec-examples.js +46 -0
  211. package/src/motion3/schema/topics.js +111 -0
  212. package/src/motion3/schema/types.js +147 -0
  213. package/src/motion3/search.js +117 -0
  214. package/src/motion3/second-hand.js +112 -0
  215. package/src/motion3/skills/basic.js +82 -0
  216. package/src/motion3/skills/book.js +76 -0
  217. package/src/motion3/skills/car.js +145 -0
  218. package/src/motion3/skills/frames-auto.js +29 -0
  219. package/src/motion3/skills/index.js +83 -0
  220. package/src/motion3/skills/info.js +65 -0
  221. package/src/motion3/skills/smoke-kit.js +109 -0
  222. package/src/motion3/skills/smoke.js +160 -0
  223. package/src/motion3/spec-store.js +59 -0
  224. package/src/motion3/take-edit.js +155 -0
  225. package/src/motion3/take.js +63 -0
  226. package/src/motion3/timeline.js +127 -0
  227. package/src/motion3/views.js +121 -0
  228. package/src/motion3/walk-plan.js +119 -0
  229. package/src/object-catalog.jsx +7 -1
  230. package/src/object-colors.js +98 -0
  231. package/src/object-gizmo-parts.js +115 -0
  232. package/src/object-gizmo.jsx +37 -122
  233. package/src/object-glow.js +139 -0
  234. package/src/object-hidden.js +33 -0
  235. package/src/object-look.js +196 -0
  236. package/src/object-size.js +10 -0
  237. package/src/object-travel.js +71 -6
  238. package/src/panels/CameraPanel.jsx +7 -7
  239. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  240. package/src/panels/LightPanel.jsx +25 -4
  241. package/src/panels/ObjectLookPanel.jsx +88 -0
  242. package/src/panels/PosePanel.jsx +2 -17
  243. package/src/panels/RigControlPanel.jsx +5 -53
  244. package/src/panels/SubjectBox.jsx +4 -1
  245. package/src/panels/details.css +14 -0
  246. package/src/posestudio.jsx +4 -27
  247. package/src/project-browser.jsx +3 -4
  248. package/src/project-resources.js +18 -31
  249. package/src/project.js +13 -104
  250. package/src/props.jsx +25 -280
  251. package/src/rail-dot-drag.js +23 -0
  252. package/src/render-passes.js +10 -0
  253. package/src/resource-status.jsx +1 -0
  254. package/src/result-modal.jsx +4 -19
  255. package/src/room.jsx +20 -12
  256. package/src/scene-assets.js +8 -6
  257. package/src/scene-light-place.js +72 -0
  258. package/src/scene-lights.jsx +148 -0
  259. package/src/scene-objects.js +31 -139
  260. package/src/scenes.js +15 -105
  261. package/src/semantic-edit.js +2 -5
  262. package/src/set-pieces.jsx +183 -0
  263. package/src/settings-menu.jsx +3 -11
  264. package/src/shell/BottomDock.jsx +9 -51
  265. package/src/shell/DetailsSlot.jsx +16 -200
  266. package/src/shell/GhostsMenuGroup.jsx +74 -0
  267. package/src/shell/LibrarySlot.jsx +1 -3
  268. package/src/shell/MenuBar.jsx +3 -3
  269. package/src/shell/PreferencesDialog.jsx +15 -264
  270. package/src/shell/PreferencesSlot.jsx +2 -8
  271. package/src/shell/TopBar.jsx +5 -84
  272. package/src/shell/ViewportToolbar.jsx +10 -70
  273. package/src/shell/agent-glass.css +19 -6
  274. package/src/shell/details-selection.js +42 -0
  275. package/src/shell/ghosts-menu.css +22 -0
  276. package/src/shell/glass-regions.css +29 -3
  277. package/src/shell/preferences.css +6 -1
  278. package/src/shot-authoring.js +4 -7
  279. package/src/soft-shadows.js +37 -0
  280. package/src/stage-attach-frames.js +12 -12
  281. package/src/stage-canvas-rigs.jsx +3 -3
  282. package/src/stage-capture.jsx +42 -8
  283. package/src/stage-characters.jsx +22 -216
  284. package/src/stage-editor-gizmos.jsx +6 -6
  285. package/src/stage-environment.js +93 -0
  286. package/src/stage-hdr-builtins.js +107 -0
  287. package/src/stage-hdr-image.js +116 -0
  288. package/src/stage-hdr-library.js +70 -0
  289. package/src/stage-hdr-map.js +94 -0
  290. package/src/stage-hdr.js +130 -0
  291. package/src/stage-lighting.js +149 -0
  292. package/src/stage-occlusion.js +210 -0
  293. package/src/stage-sky.jsx +159 -0
  294. package/src/stage-startup-defaults.js +5 -9
  295. package/src/studio-actions.js +12 -14
  296. package/src/studio-agent-commands.js +19 -16
  297. package/src/studio-agent-motion.js +9 -9
  298. package/src/studio-agent-protocol.js +41 -71
  299. package/src/studio-app-binding.js +25 -45
  300. package/src/studio-asset-list.js +17 -0
  301. package/src/studio-contact-sheet.js +37 -5
  302. package/src/studio-elements.js +27 -7
  303. package/src/studio-entity-bounds.js +18 -0
  304. package/src/studio-error-codes.js +8 -0
  305. package/src/studio-export-framing.js +152 -0
  306. package/src/studio-lighting-check.js +103 -0
  307. package/src/studio-motion-visual.js +150 -0
  308. package/src/studio-schema-errors.js +80 -0
  309. package/src/studio-support-gap.js +74 -0
  310. package/src/styles.css +1 -19
  311. package/src/timeline-defaults.js +5 -0
  312. package/src/timeline-extent.js +8 -20
  313. package/src/tutorial-walk.js +17 -0
  314. package/src/ui-scrub.js +1 -1
  315. package/src/use-shot-camera-tracks.js +12 -0
  316. package/src/view-ghosts.js +97 -0
  317. package/src/view-ghosts.jsx +49 -0
  318. package/src/workflow/AgentPanel.jsx +47 -166
  319. package/src/workflow/AgentProgressCard.jsx +107 -0
  320. package/src/workflow/AgentReplyText.jsx +37 -0
  321. package/src/workflow/AgentTurnSteps.jsx +84 -0
  322. package/src/workflow/LoginPanel.jsx +140 -0
  323. package/src/workflow/WorkflowBuilder.jsx +7 -23
  324. package/src/workflow/agent-client.js +54 -51
  325. package/src/workflow/agent-panel.css +71 -1
  326. package/src/workflow/agent-progress-card.css +167 -0
  327. package/src/workflow/agent-progress-view.js +47 -0
  328. package/src/workflow/agent-turn-steps.css +113 -0
  329. package/src/workflow/agent-turn.js +191 -0
  330. package/src/workflow/login-client.js +34 -0
  331. package/src/workflow/motion-input.js +18 -31
  332. package/src/workflow/node-schema.js +1 -1
  333. package/src/workflow/reply-markdown.js +69 -0
  334. package/src/workflow/scene-asset-sync.js +8 -8
  335. package/tools/agent-session-stats.mjs +61 -0
  336. package/tools/dev-full.mjs +5 -56
  337. package/tools/eslint-baseline.json +12 -13
  338. package/tools/knip-baseline.json +0 -179
  339. package/tools/loc-baseline.json +31 -81
  340. package/tools/motion3/extract-body.mjs +103 -0
  341. package/tools/motion3/extract-rig.mjs +85 -0
  342. package/tools/process-supervisor.mjs +0 -88
  343. package/tools/run-tests.mjs +8 -124
  344. package/bin/agent/motion-runtime.mjs +0 -76
  345. package/dist/ardy/cskel27-rest.json +0 -557
  346. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  347. package/dist/assets/app-B_2XB9rw.css +0 -1
  348. package/dist/assets/app-DAuvKPP8.js +0 -4920
  349. package/dist/assets/config-Bx7pYsD9.js +0 -1
  350. package/dist/assets/config-DeoFTYzb.css +0 -1
  351. package/dist/assets/demo-CvKuBgy5.js +0 -1
  352. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  353. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  354. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  355. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  356. package/dist/demo/walk-then-stop.npz +0 -0
  357. package/mcp/ardy-prompts.mjs +0 -218
  358. package/src/ardy/auto-fix-panel.css +0 -108
  359. package/src/ardy/auto-physics.js +0 -1194
  360. package/src/ardy/client.js +0 -153
  361. package/src/ardy/convert.js +0 -313
  362. package/src/ardy/cskel27-neutral.js +0 -39
  363. package/src/ardy/cskel27.js +0 -77
  364. package/src/ardy/export.js +0 -165
  365. package/src/ardy/fix-collisions.js +0 -2257
  366. package/src/ardy/foot-lock.js +0 -230
  367. package/src/ardy/motion-calibration.js +0 -118
  368. package/src/ardy/motion-edit.js +0 -213
  369. package/src/ardy/motion-url.js +0 -55
  370. package/src/ardy/mp4-duration.js +0 -102
  371. package/src/ardy/npz.js +0 -595
  372. package/src/ardy/physics-panel.css +0 -21
  373. package/src/ardy/physics-panel.jsx +0 -89
  374. package/src/ardy/physics-refine.js +0 -111
  375. package/src/ardy/physics-review.js +0 -567
  376. package/src/ardy/physics-temporal.js +0 -54
  377. package/src/ardy/platform-fit-panel.css +0 -64
  378. package/src/ardy/platform-fit-panel.jsx +0 -41
  379. package/src/ardy/platform-fit.js +0 -326
  380. package/src/ardy/playback.js +0 -711
  381. package/src/ardy/pose-pin.js +0 -97
  382. package/src/ardy/prompt-clips.js +0 -30
  383. package/src/ardy/retime.js +0 -211
  384. package/src/ardy/root-drop.js +0 -369
  385. package/src/ardy/timeline-resize.js +0 -13
  386. package/src/ardy/to-cskel27.js +0 -225
  387. package/src/ardy/trim.js +0 -33
  388. package/src/ardy/waypoints.js +0 -369
  389. package/src/ardy-bridge-contract.js +0 -281
  390. package/src/domains/motion/motion-video-capture.js +0 -664
  391. package/src/i2v-motion-client.js +0 -77
  392. package/src/i2v-motion-studio.jsx +0 -180
  393. package/src/line-edit.js +0 -1348
  394. package/src/motion/generation.js +0 -105
  395. package/src/motion-readiness-ui.jsx +0 -67
  396. package/src/motion-readiness.js +0 -40
  397. package/src/motion-resources.js +0 -177
  398. package/src/motion-store.js +0 -65
  399. package/src/motion-trail.js +0 -601
  400. package/src/multimodel-ingest.js +0 -394
  401. package/src/panels/PromptBlocksPanel.jsx +0 -444
  402. package/src/panels/VideoCapturePanel.jsx +0 -181
  403. package/src/pose-extract/browser.js +0 -42
  404. package/src/pose-extract/detector.js +0 -100
  405. package/src/pose-extract/fit.js +0 -227
  406. package/src/pose-extract/image-frame.js +0 -51
  407. package/src/pose-extract/index.js +0 -58
  408. package/src/pose-extract/keyframes.js +0 -74
  409. package/src/pose-extract/landmarks.js +0 -162
  410. package/src/pose-extract/mirror.js +0 -153
  411. package/src/pose-extract/take.js +0 -131
  412. package/src/pose-extract/video-frames.js +0 -91
  413. package/src/take-recipe.js +0 -165
  414. package/src/trail-key-conflicts.js +0 -39
  415. package/src/trail-pick.js +0 -59
  416. package/src/use-i2v-capture-modal.js +0 -15
  417. package/tools/ardy/BRIDGE.md +0 -37
  418. package/tools/ardy/GVHMR-NPZ.md +0 -68
  419. package/tools/ardy/README.md +0 -124
  420. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  421. package/tools/ardy/artifacts.mjs +0 -34
  422. package/tools/ardy/bridge.mjs +0 -1732
  423. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  424. package/tools/ardy/cclay_constrained_generate.py +0 -561
  425. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  426. package/tools/ardy/cclay_motion_edit.py +0 -510
  427. package/tools/ardy/cclay_sequence_generate.py +0 -705
  428. package/tools/ardy/cclay_worker.py +0 -304
  429. package/tools/ardy/dump-npz.py +0 -205
  430. package/tools/ardy/extract-rest.mjs +0 -299
  431. package/tools/ardy/extract.mjs +0 -507
  432. package/tools/ardy/footage.mjs +0 -467
  433. package/tools/ardy/gvhmr-floor.mjs +0 -102
  434. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  435. package/tools/ardy/gvhmr_fastpath.py +0 -168
  436. package/tools/ardy/gvhmr_trajectory.py +0 -240
  437. package/tools/ardy/merge-text-encoder.py +0 -160
  438. package/tools/ardy/mocap-metrics.mjs +0 -200
  439. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  440. package/tools/ardy/motion-stabilize.mjs +0 -348
  441. package/tools/ardy/npz.mjs +0 -414
  442. package/tools/ardy/pose-to-npz.mjs +0 -106
  443. package/tools/ardy/prompt-limits.mjs +0 -5
  444. package/tools/ardy/run-edit-on-box.sh +0 -73
  445. package/tools/ardy/run-local.mjs +0 -233
  446. package/tools/ardy/run-on-box.sh +0 -593
  447. package/tools/ardy/run-sequence-on-box.sh +0 -177
  448. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  449. package/tools/ardy/runners/index.mjs +0 -18
  450. package/tools/ardy/runners/local.mjs +0 -455
  451. package/tools/ardy/runners/proc.mjs +0 -125
  452. package/tools/ardy/runners/remote.mjs +0 -252
  453. package/tools/ardy/setup-local.mjs +0 -189
  454. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  455. package/tools/ardy/setup-text-encoder.py +0 -306
  456. package/tools/ardy/smpl-cskel27.mjs +0 -178
  457. package/tools/ardy/visual-qa.mjs +0 -196
  458. package/tools/ardy/vq-car.mjs +0 -52
  459. package/tools/bench/EXP3.md +0 -61
  460. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  461. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  462. package/tools/bench/cclay_bench_runner.py +0 -42
  463. package/tools/bench/cube-contact.mjs +0 -162
  464. package/tools/bench/exp3.mjs +0 -152
  465. package/tools/bench/extract-bench-lib.mjs +0 -216
  466. package/tools/bench/extract-bench.mjs +0 -302
  467. package/tools/bench/fal-generate.mjs +0 -88
  468. package/tools/bench/fit/README.md +0 -189
  469. package/tools/bench/fit/camera.mjs +0 -59
  470. package/tools/bench/fit/contact.mjs +0 -419
  471. package/tools/bench/fit/footlock.mjs +0 -234
  472. package/tools/bench/fit/motion.mjs +0 -85
  473. package/tools/bench/fit/pin.mjs +0 -27
  474. package/tools/bench/fit/remote.mjs +0 -105
  475. package/tools/bench/fit-bench.mjs +0 -126
  476. package/tools/bench/fit-sanity.mjs +0 -45
  477. package/tools/bench/metrics.mjs +0 -313
  478. package/tools/bench/obs/depth.mjs +0 -258
  479. package/tools/bench/obs/extrinsics.mjs +0 -175
  480. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  481. package/tools/bench/obs/ground.mjs +0 -294
  482. package/tools/bench/obs/heading.mjs +0 -151
  483. package/tools/bench/obs/ladder.mjs +0 -555
  484. package/tools/bench/obs/mannequin-betas.json +0 -124
  485. package/tools/bench/obs/remote.mjs +0 -83
  486. package/tools/bench/obs/rest_joints.py +0 -52
  487. package/tools/bench/obs/ybot-targets.mjs +0 -49
  488. package/tools/bench/obs-bench.mjs +0 -520
  489. package/tools/bench/score.mjs +0 -343
  490. package/tools/bench/summarize.mjs +0 -86
  491. package/tools/demo-worker/README.md +0 -137
  492. package/tools/demo-worker/api-client.mjs +0 -233
  493. package/tools/demo-worker/generate.mjs +0 -301
  494. package/tools/demo-worker/index.mjs +0 -466
  495. package/tools/demo-worker/sign-core.mjs +0 -112
  496. package/tools/demo-worker/sign.mjs +0 -161
  497. package/tools/gt-render/browser.mjs +0 -182
  498. package/tools/gt-render/camera-math.mjs +0 -276
  499. package/tools/gt-render/page.mjs +0 -267
  500. package/tools/gt-render/render.mjs +0 -514
  501. package/tools/gt-render/scene-box.mjs +0 -31
  502. package/tools/gt-render/take-transform.mjs +0 -87
  503. package/tools/kimodo/compare-seam.mjs +0 -108
  504. package/tools/kimodo/constraints.mjs +0 -244
  505. package/tools/kimodo/edit.mjs +0 -259
  506. package/tools/kimodo/effector-constraints.mjs +0 -200
  507. package/tools/kimodo/generate.mjs +0 -646
  508. package/tools/kimodo/local-output.mjs +0 -265
  509. package/tools/kimodo/measure-pose.mjs +0 -65
  510. package/tools/kimodo/measure-preserve.mjs +0 -899
  511. package/tools/kimodo/measure-waypoints.mjs +0 -55
  512. package/tools/kimodo/mlx-generate.py +0 -111
  513. package/tools/kimodo/pose-constraints.mjs +0 -248
  514. package/tools/kimodo/preserve-mask.mjs +0 -543
  515. package/tools/kimodo/read-npz.mjs +0 -189
  516. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  517. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  518. package/tools/kimodo/runner.mjs +0 -284
  519. package/tools/kimodo/seam-batch.mjs +0 -77
  520. package/tools/kimodo/setup-local.mjs +0 -30
  521. package/tools/kimodo/setup-on-box.sh +0 -339
  522. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  523. package/tools/morphgs/assets/gen_truth.py +0 -39
  524. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  525. package/tools/morphgs/assets/playback-check.mjs +0 -30
  526. package/tools/morphgs/demo-gate.sh +0 -26
  527. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  528. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  529. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  530. package/tools/morphgs/setup-on-cluster.sh +0 -126
  531. package/tools/projflow/driver.py +0 -1069
  532. package/tools/projflow/generate.mjs +0 -805
  533. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  534. package/tools/projflow/line-edit-job.mjs +0 -547
  535. package/tools/projflow/replay.mjs +0 -452
  536. package/tools/projflow/runner.mjs +0 -269
  537. package/tools/projflow/service.mjs +0 -742
  538. package/tools/track/DESIGN.md +0 -513
  539. package/tools/track/backfill-provenance.mjs +0 -116
  540. package/tools/track/budget.mjs +0 -8
  541. package/tools/track/check-rig.mjs +0 -209
  542. package/tools/track/diagnostics.schema.json +0 -60
  543. package/tools/track/export-rig.mjs +0 -256
  544. package/tools/track/fallback.mjs +0 -7
  545. package/tools/track/fk-parity-fixture.mjs +0 -161
  546. package/tools/track/gate.mjs +0 -349
  547. package/tools/track/masks.mjs +0 -318
  548. package/tools/track/metrics.mjs +0 -201
  549. package/tools/track/publish-obs.mjs +0 -108
  550. package/tools/track/py/check_env.py +0 -61
  551. package/tools/track/py/eval_lr.py +0 -229
  552. package/tools/track/py/lr_viterbi.py +0 -294
  553. package/tools/track/py/masks.py +0 -405
  554. package/tools/track/py/objective.py +0 -382
  555. package/tools/track/py/rig.py +0 -508
  556. package/tools/track/py/scene.py +0 -326
  557. package/tools/track/py/test_joint_indices.py +0 -123
  558. package/tools/track/py/test_lr_viterbi.py +0 -195
  559. package/tools/track/py/test_masks.py +0 -229
  560. package/tools/track/py/test_rig.py +0 -288
  561. package/tools/track/py/test_scene.py +0 -354
  562. package/tools/track/py/test_track.py +0 -328
  563. package/tools/track/py/track.py +0 -411
  564. package/tools/track/remote.mjs +0 -140
  565. package/tools/track/rig-dump.mjs +0 -227
  566. package/tools/track/run-box-tests.mjs +0 -14
  567. package/tools/track/run-box.mjs +0 -168
  568. package/tools/track/setup-box.sh +0 -59
  569. package/tools/track/study-2d.mjs +0 -728
  570. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  571. /package/src/{ardy → motion}/ground.js +0 -0
  572. /package/src/{ardy → motion}/ik-drag.js +0 -0
  573. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  574. /package/src/{ardy → motion}/ik.js +0 -0
  575. /package/src/{ardy → motion}/physics-surface.js +0 -0
  576. /package/src/{ardy → motion}/playback-clock.js +0 -0
  577. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -1,369 +0,0 @@
1
- import { sliceMotion } from "./trim.js";
2
-
3
- // A vertical drop authored ONTO a take. ARDY generates motion on flat
4
- // ground — nothing in a generated clip can carry a body off a 14 m roof.
5
- // The plunge is previs staging, not motion synthesis, so it is applied to
6
- // the decoded clip as a rigid vertical offset: every joint of a frame moves
7
- // down by the same amount, and the amount follows a gravity curve.
8
- //
9
- // Seconds, not frames: a take crosses two clocks on its way in (ARDY's
10
- // 20 fps, the 24 fps production timeline), and a boundary in seconds means
11
- // the caller never has to know which side of the retime it is speaking to.
12
-
13
- /** Validated {fromS, toS, meters} or null — malformed input is no drop. */
14
- export function normalizeRootDrop(drop) {
15
- if (!drop || typeof drop !== "object" || Array.isArray(drop)) return null;
16
- const fromS = Number(drop.fromS ?? drop.from_s);
17
- const toS = Number(drop.toS ?? drop.to_s);
18
- const meters = Number(drop.meters);
19
- if (!Number.isFinite(fromS) || !Number.isFinite(toS) || !Number.isFinite(meters)) return null;
20
- if (fromS < 0 || toS <= fromS || meters <= 0) return null;
21
- return { fromS, toS, meters };
22
- }
23
-
24
- /** Point-in-footprint on the floor plane, honouring the support's yaw. */
25
- function insideSupport(support, px, pz) {
26
- const yaw = ((support.rotDeg ?? 0) * Math.PI) / 180;
27
- const cos = Math.cos(yaw);
28
- const sin = Math.sin(yaw);
29
- const dx = px - support.x;
30
- const dz = pz - support.z;
31
- const lx = cos * dx - sin * dz;
32
- const lz = sin * dx + cos * dz;
33
- return Math.abs(lx) <= support.width / 2 && Math.abs(lz) <= support.depth / 2;
34
- }
35
-
36
- const SUPPORT_FEET = [21, 22, 25, 26];
37
- const smoothstep = (value) => {
38
- const t = Math.max(0, Math.min(1, value));
39
- return t * t * (3 - 2 * t);
40
- };
41
-
42
- /**
43
- * Lift a take onto an explicitly authored scene surface. ARDY clips are
44
- * normally rooted on the deck, so a performer climbing onto a prop needs a
45
- * small, time-continuous offset while their root is inside that prop's
46
- * footprint. We require a real upward root trend before applying anything;
47
- * a flat walk through a prop therefore stays untouched.
48
- *
49
- * `supports` are world-space rectangles with an explicit `supportY` (the top
50
- * of the surface). `subjectX/Y/Z` supply the character's scene anchor and
51
- * `worldScale` converts canonical clip units to scene metres, matching the
52
- * transform used by `autoRoofDrop`. The input motion is never mutated. The
53
- * returned object carries `surfaceRise` diagnostics.
54
- */
55
- export function applySupportRise(
56
- motion,
57
- supports,
58
- { subjectX = 0, subjectY = 0, subjectZ = 0, rotationDeg = 0, minRise = 0.08, minSlope = 0.04, lookbackFrames = 6, blendFrames = 6, maxOffset = 1.5, worldScale = 1 } = {},
59
- ) {
60
- if (!motion || !Number.isFinite(motion.fps) || motion.fps <= 0 || !motion.rootPos || !motion.posedJoints) return motion;
61
- const frames = Number(motion.frames);
62
- if (!Number.isInteger(frames) || frames < 2 || motion.rootPos.length < frames * 3) return motion;
63
- const joints = motion.posedJoints.length / (frames * 3);
64
- if (!Number.isInteger(joints) || joints <= 0) return motion;
65
- const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
66
- if (!Array.isArray(supports) || !supports.length) return motion;
67
- const candidates = supports.filter((support) =>
68
- support && Number.isFinite(Number(support.supportY)) && Number(support.width) > 0 && Number(support.depth) > 0,
69
- );
70
- if (!candidates.length) return motion;
71
- const radians = (Number(rotationDeg) || 0) * Math.PI / 180;
72
- const cos = Math.cos(radians), sin = Math.sin(radians);
73
- const worldAt = (frame) => {
74
- const dx = motion.rootPos[frame * 3] - motion.rootPos[0];
75
- const dz = motion.rootPos[frame * 3 + 2] - motion.rootPos[2];
76
- return { x: Number(subjectX) + (dx * cos + dz * sin) * scale, z: Number(subjectZ) + (-dx * sin + dz * cos) * scale };
77
- };
78
- const points = Array.from({ length: frames }, (_, frame) => worldAt(frame));
79
- const feet = SUPPORT_FEET.filter((joint) => joint < joints);
80
- const footWorldAt = (frame, joint) => {
81
- const p = (frame * joints + joint) * 3;
82
- // posedJoints and rootPos are both frame-local; subtract the root from
83
- // the same frame before rotating into world space. Using frame zero here
84
- // made a walking foot drift with the accumulated root travel and caused
85
- // support detection to miss later chair/platform contacts.
86
- const dx = motion.posedJoints[p] - motion.rootPos[frame * 3];
87
- const dz = motion.posedJoints[p + 2] - motion.rootPos[frame * 3 + 2];
88
- return { x: Number(subjectX) + (dx * cos + dz * sin) * scale, z: Number(subjectZ) + (-dx * sin + dz * cos) * scale };
89
- };
90
- const inside = candidates.map((support) => points.map((point, frame) => insideSupport({
91
- x: Number(support.x) || 0, z: Number(support.z) || 0,
92
- rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
93
- }, point.x, point.z) || feet.some((joint) => {
94
- const foot = footWorldAt(frame, joint);
95
- return insideSupport({
96
- x: Number(support.x) || 0, z: Number(support.z) || 0,
97
- rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
98
- }, foot.x, foot.z);
99
- })));
100
- let selected = null;
101
- for (let si = 0; si < candidates.length; si += 1) {
102
- const support = candidates[si];
103
- // A performer often enters a prop's footprint before lifting a foot
104
- // (approach, brace, then climb). Search the first second of continuous
105
- // support occupancy instead of requiring the rise on the boundary frame.
106
- let entry = -1;
107
- for (let frame = 0; frame < frames; frame += 1) {
108
- if (!inside[si][frame]) { entry = -1; continue; }
109
- // A take can begin already standing on a platform. Treat frame 0 as
110
- // an entry so the same evidence search handles both approaches and
111
- // starts-on-support clips.
112
- if (entry < 0 && (frame === 0 || !inside[si][frame - 1])) entry = frame;
113
- if (entry < 0 || frame - entry > Math.round(motion.fps)) continue;
114
- const from = Math.max(0, frame - Math.max(1, Math.round(lookbackFrames)));
115
- // A foot can enter the footprint one or two frames before the body
116
- // commits to the climb. Look a short distance ahead, while retaining
117
- // the entry frame as the point where the blend begins.
118
- const evidenceFrame = Math.min(frames - 1, frame + Math.max(1, Math.round(lookbackFrames)));
119
- const rise = (motion.rootPos[evidenceFrame * 3 + 1] - motion.rootPos[from * 3 + 1]) * scale;
120
- const slope = rise / ((evidenceFrame - from) / motion.fps);
121
- if (rise < Number(minRise) || slope < Number(minSlope)) continue;
122
- if (!feet.length) continue;
123
- const supportRect = {
124
- x: Number(support.x) || 0, z: Number(support.z) || 0,
125
- rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
126
- };
127
- const occupiedYs = [];
128
- for (let probe = evidenceFrame; probe < frames && inside[si][probe] && probe <= evidenceFrame + Math.round(motion.fps * 0.75); probe += 1) {
129
- // A climb often straddles the deck and the prop: one foot remains
130
- // on the floor while the other is already on the seat. Measuring the
131
- // minimum of *all* feet therefore used the deck foot as the seat
132
- // datum and left the climbing foot below the authored support. Use
133
- // only feet whose XZ footprint is actually on this support.
134
- const onSupport = feet.filter((joint) => {
135
- const foot = footWorldAt(probe, joint);
136
- return insideSupport(supportRect, foot.x, foot.z);
137
- });
138
- // Root occupancy is valid evidence while the pelvis is over a support
139
- // but the feet have not entered its rectangle yet. In that phase keep
140
- // the legacy all-foot fallback; once a foot is actually on the support,
141
- // use only those feet so a deck foot cannot set the seat datum.
142
- const ys = (onSupport.length ? onSupport : feet)
143
- .map((joint) => motion.posedJoints[(probe * joints + joint) * 3 + 1] * scale).filter(Number.isFinite);
144
- // If a second foot is still on the deck but its footprint overlaps
145
- // the prop edge, the lower sample is not the seat contact. The upper
146
- // supported foot is the conservative datum; when both feet are on
147
- // the same surface their heights agree.
148
- if (ys.length) occupiedYs.push(Math.max(...ys));
149
- }
150
- occupiedYs.sort((a, b) => a - b);
151
- const observedFootY = occupiedYs[Math.floor(occupiedYs.length * 0.7)];
152
- const onSupportAtEvidence = feet.filter((joint) => {
153
- const foot = footWorldAt(evidenceFrame, joint);
154
- return insideSupport(supportRect, foot.x, foot.z);
155
- });
156
- const footYs = (onSupportAtEvidence.length ? onSupportAtEvidence : feet)
157
- .map((joint) => motion.posedJoints[(evidenceFrame * joints + joint) * 3 + 1] * scale).filter(Number.isFinite);
158
- if (!footYs.length) continue;
159
- const baseY = Number(subjectY) || 0;
160
- const offsetWorld = Number(support.supportY) - (baseY + (Number.isFinite(observedFootY) ? observedFootY : Math.min(...footYs)));
161
- if (!(offsetWorld > 0.01) || offsetWorld > Number(maxOffset)) continue;
162
- selected = {
163
- si,
164
- frame,
165
- support,
166
- offset: offsetWorld / scale,
167
- offsetWorld,
168
- rise,
169
- slope,
170
- baseRootY: motion.rootPos[from * 3 + 1],
171
- };
172
- break;
173
- }
174
- if (selected) break;
175
- }
176
- if (!selected) return motion;
177
- const { si, frame: enter, offset, offsetWorld, support, rise, slope, baseRootY } = selected;
178
- let exit = frames - 1;
179
- for (let frame = enter + 1; frame < frames; frame += 1) {
180
- if (!inside[si][frame]) { exit = frame; break; }
181
- }
182
- // Some shots climb and then step down while the root remains inside a
183
- // generous footprint (a chair turn, a platform landing, or a jump in
184
- // place). Release the lift when the root has come back near its pre-climb
185
- // level; otherwise the rigid support offset would leave the performer
186
- // floating even though the take has visibly descended.
187
- let release = exit;
188
- const descendThreshold = Math.max(Number(minRise), 0.08);
189
- let peakRootY = motion.rootPos[enter * 3 + 1];
190
- for (let frame = enter + 1; frame <= exit; frame += 1) {
191
- peakRootY = Math.max(peakRootY, motion.rootPos[frame * 3 + 1]);
192
- const current = motion.rootPos[frame * 3 + 1];
193
- if (peakRootY - current >= descendThreshold && current <= baseRootY + descendThreshold * 0.5) {
194
- release = frame;
195
- break;
196
- }
197
- }
198
- const blend = Math.max(1, Math.round(blendFrames));
199
- const offsets = new Float32Array(frames);
200
- for (let frame = enter; frame < frames; frame += 1) {
201
- const up = smoothstep((frame - enter + 1) / blend);
202
- const down = release < frames - 1 ? smoothstep((release - frame) / blend) : 1;
203
- offsets[frame] = offset * Math.min(up, down);
204
- }
205
- const rootPos = Float32Array.from(motion.rootPos);
206
- const posedJoints = Float32Array.from(motion.posedJoints);
207
- const jointCount = Math.round(posedJoints.length / frames / 3);
208
- for (let frame = 0; frame < frames; frame += 1) {
209
- const dy = offsets[frame];
210
- if (!dy) continue;
211
- rootPos[frame * 3 + 1] += dy;
212
- for (let joint = 0; joint < jointCount; joint += 1) posedJoints[(frame * jointCount + joint) * 3 + 1] += dy;
213
- }
214
- return {
215
- ...motion,
216
- rootPos,
217
- posedJoints,
218
- surfaceRise: { applied: true, supportY: Number(support.supportY), offset, offsetWorld, worldScale: scale, enterFrame: enter, exitFrame: exit, releaseFrame: release, rise, slope },
219
- };
220
- }
221
-
222
- /**
223
- * Stage a fall the author did not have to ask for: a character standing on a
224
- * raised support (a roof — place_character's y) whose take walks past the
225
- * support's edge should drop, because ARDY only generates flat-ground motion.
226
- *
227
- * `subject` is { x, z, y, rotationDeg } — the character's blocking, with the
228
- * take's root rotation. `supports` are world-space tops: { x, z, rotDeg,
229
- * topY, width, depth }. The walk is sampled with the same root convention
230
- * playback uses (frame-zero anchored, yaw-rotated into scene space).
231
- *
232
- * Returns a { fromS, toS, meters } drop, or null when the character is on
233
- * the ground, never stood on a support, or never leaves it — null means
234
- * "stage nothing", so this is safe to leave on the load path.
235
- */
236
- export function autoRoofDrop(motion, subject, supports, { gravity = 9.81, topTolerance = 0.3, fallTimeScale = 1.15, worldScale = 1 } = {}) {
237
- if (!motion || !Number.isFinite(motion.fps) || motion.fps <= 0 || !motion.rootPos) return null;
238
- const frames = motion.frames;
239
- if (!Number.isFinite(frames) || frames < 2) return null;
240
- const y = Number(subject?.y) || 0;
241
- if (y <= 0.05 || !Array.isArray(supports) || supports.length === 0) return null;
242
- const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
243
-
244
- const radians = ((Number.isFinite(subject.rotationDeg) ? subject.rotationDeg : 0) * Math.PI) / 180;
245
- const cos = Math.cos(radians);
246
- const sin = Math.sin(radians);
247
- const worldAt = (frame) => {
248
- const dx = motion.rootPos[frame * 3] - motion.rootPos[0];
249
- const dz = motion.rootPos[frame * 3 + 2] - motion.rootPos[2];
250
- return {
251
- x: subject.x + (dx * cos + dz * sin) * scale,
252
- z: subject.z + (-dx * sin + dz * cos) * scale,
253
- };
254
- };
255
-
256
- const start = worldAt(0);
257
- const carriers = supports.filter((support) =>
258
- support.width > 0 && support.depth > 0 &&
259
- Math.abs(support.topY - y) <= topTolerance &&
260
- insideSupport(support, start.x, start.z));
261
- if (carriers.length === 0) return null;
262
-
263
- for (let frame = 1; frame < frames; frame += 1) {
264
- const point = worldAt(frame);
265
- if (carriers.some((support) => insideSupport(support, point.x, point.z))) continue;
266
- // Land on the tallest lower support under the exit point, else the street.
267
- const landing = supports.reduce((top, support) =>
268
- support.topY < y - topTolerance && support.topY > top && insideSupport(support, point.x, point.z)
269
- ? support.topY
270
- : top, 0);
271
- const meters = y - landing;
272
- if (meters <= 0) return null;
273
- const fromS = frame / motion.fps;
274
- // Near-real gravity: a lightly stretched clock keeps weight without
275
- // drifting into moon-fall. The readability comes from applyAutoFall's
276
- // ballistic arc and impact cut, not from slowing the clock down.
277
- return { fromS, toS: fromS + Math.sqrt((2 * meters) / gravity) * fallTimeScale, meters };
278
- }
279
- return null;
280
- }
281
-
282
- /**
283
- * Bake an auto-staged fall so it reads like a stunt, not a glitch:
284
- * - past the edge the root leaves the authored walk path and flies a true
285
- * ballistic arc — the exit velocity carries, gravity owns the vertical;
286
- * - the horizontal drift stops at impact (bodies do not keep strolling);
287
- * - the take is cut just after the landing, because whatever the flat-ground
288
- * clip does next (walking away twelve metres underground-level) is comedy.
289
- * Explicit MCP drops keep the rigid applyRootDrop bake below.
290
- */
291
- export function applyAutoFall(motion, spec, { landHoldS = 0.35, launchLookbackS = 0.15, worldScale = 1 } = {}) {
292
- if (!spec || !motion || !Number.isFinite(motion.fps) || motion.fps <= 0) return motion;
293
- const fps = motion.fps;
294
- const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
295
- const fExit = Math.max(0, Math.round(spec.fromS * fps));
296
- if (fExit >= motion.frames - 1) return motion;
297
- const fallS = Math.max(spec.toS - spec.fromS, 1 / fps);
298
- const joints = Math.round(motion.posedJoints.length / motion.frames / 3);
299
- const rootPos = Float32Array.from(motion.rootPos);
300
- const posedJoints = Float32Array.from(motion.posedJoints);
301
- const lookback = Math.max(1, Math.round(launchLookbackS * fps));
302
- const f0 = Math.max(0, fExit - lookback);
303
- const span = Math.max(1, fExit - f0);
304
- const vx = ((rootPos[fExit * 3] - rootPos[f0 * 3]) / span) * fps;
305
- const vz = ((rootPos[fExit * 3 + 2] - rootPos[f0 * 3 + 2]) / span) * fps;
306
- const exitX = rootPos[fExit * 3];
307
- const exitZ = rootPos[fExit * 3 + 2];
308
- const fLand = Math.min(motion.frames - 1, Math.ceil(spec.toS * fps));
309
- for (let f = fExit + 1; f < motion.frames; f += 1) {
310
- const t = (f - fExit) / fps;
311
- const progress = Math.min(t / fallS, 1);
312
- const air = Math.min(t, fallS);
313
- const dy = -(spec.meters / scale) * progress * progress;
314
- const dx = exitX + vx * air - rootPos[f * 3];
315
- const dz = exitZ + vz * air - rootPos[f * 3 + 2];
316
- rootPos[f * 3] += dx;
317
- rootPos[f * 3 + 1] += dy;
318
- rootPos[f * 3 + 2] += dz;
319
- for (let j = 0; j < joints; j += 1) {
320
- const base = (f * joints + j) * 3;
321
- posedJoints[base] += dx;
322
- posedJoints[base + 1] += dy;
323
- posedJoints[base + 2] += dz;
324
- }
325
- }
326
- const rotMats = Float32Array.from(motion.rotMats);
327
- for (let f = fLand + 1; f < motion.frames; f += 1) {
328
- rootPos.set(rootPos.subarray(fLand * 3, fLand * 3 + 3), f * 3);
329
- posedJoints.set(
330
- posedJoints.subarray(fLand * joints * 3, (fLand + 1) * joints * 3),
331
- f * joints * 3,
332
- );
333
- rotMats.set(
334
- rotMats.subarray(fLand * joints * 9, (fLand + 1) * joints * 9),
335
- f * joints * 9,
336
- );
337
- }
338
- const baked = { ...motion, rootPos, posedJoints, rotMats };
339
- const fEnd = Math.min(motion.frames - 1, Math.ceil((spec.toS + landHoldS) * fps));
340
- return fEnd < motion.frames - 1 ? sliceMotion(baked, 0, fEnd) : baked;
341
- }
342
-
343
- /**
344
- * The clip with the drop applied. The input clip is never mutated — the
345
- * caller may hold it as a trim source — and an invalid drop returns the
346
- * clip untouched, so this is safe to leave on the load path unconditionally.
347
- *
348
- * The curve is t² (uniform acceleration): a body leaving a roof gathers
349
- * speed, and an eased-both-ends fall reads as a elevator, not gravity.
350
- */
351
- export function applyRootDrop(motion, drop, { worldScale = 1 } = {}) {
352
- const spec = normalizeRootDrop(drop);
353
- if (!spec || !motion || !Number.isFinite(motion.fps) || motion.fps <= 0) return motion;
354
- const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
355
- const frames = motion.frames;
356
- if (!Number.isFinite(frames) || frames <= 0) return motion;
357
-
358
- const posedJoints = Float32Array.from(motion.posedJoints);
359
- const rootPos = Float32Array.from(motion.rootPos);
360
- const joints = Math.round(posedJoints.length / frames / 3);
361
- for (let f = 0; f < frames; f += 1) {
362
- const t = Math.min(Math.max((f / motion.fps - spec.fromS) / (spec.toS - spec.fromS), 0), 1);
363
- if (t === 0) continue;
364
- const dy = -(spec.meters / scale) * t * t;
365
- for (let j = 0; j < joints; j += 1) posedJoints[(f * joints + j) * 3 + 1] += dy;
366
- rootPos[f * 3 + 1] += dy;
367
- }
368
- return { ...motion, posedJoints, rootPos };
369
- }
@@ -1,13 +0,0 @@
1
- import { TIMELINE_FRAME_FPS } from "../scenes.js";
2
-
3
- const PROMPT_BLOCK_FRAMES = 2 * TIMELINE_FRAME_FPS;
4
- const PROMPT_RESIZE_BLOCK_PX = 120; // one deliberate drag step = one prompt block
5
-
6
- /** Resize from the immutable pointer-down frame. Keeping both the frame and
7
- * pixel origin fixed prevents a growing timeline from feeding its new frame
8
- * count back into the next pointermove and exploding exponentially. */
9
- export function promptResizeFrame(startFrame, startClientX, clientX) {
10
- const blocks = (clientX - startClientX) / PROMPT_RESIZE_BLOCK_PX;
11
- const blockDelta = Math.sign(blocks) * Math.round(Math.abs(blocks));
12
- return startFrame + blockDelta * PROMPT_BLOCK_FRAMES;
13
- }
@@ -1,225 +0,0 @@
1
- /**
2
- * CozyClayPoseV1 -> the two npz arrays cclay_constrained_generate.load_poses
3
- * reads (local_rot_mats 27x3x3, posed_joints 27x3; the generator then runs its
4
- * own FK, consulting only posed_joints[0] as the root).
5
- *
6
- * The 19 joints CozyClay authors map through each Mixamo bone's armature-space
7
- * rest rotation Rb (cskel27-rest.json): L = Rb @ basis @ Rb^T. ARDY has four
8
- * torso segments where Mixamo has three, so Mixamo Spine/Spine1 target ARDY
9
- * Spine1/Spine2, matching playback's map. The remaining joints get identity;
10
- * `filled_identity` records them and `rotation_constraint_indices` identifies
11
- * the rotations that are genuinely authored.
12
- *
13
- * Proportions are never hardcoded: bone offsets come from the reference frame
14
- * of the same base clip the pose will constrain (mirroring
15
- * motion_constraints.derive_bone_offsets), and the root rides on that frame's
16
- * own root. If ARDY ever reproportions cskel27, the clip proportions stay
17
- * correct by construction.
18
- */
19
-
20
- import {
21
- COZYCLAY_BONES,
22
- COZYCLAY_TO_CSKEL27,
23
- CSKEL27_JOINTS,
24
- } from "./cskel27.js";
25
- import { CSKEL27_NEUTRAL } from "./cskel27-neutral.js";
26
- import {
27
- basisQuaternionToLocalRotation,
28
- deriveBoneOffsets,
29
- forwardKinematics,
30
- } from "./convert.js";
31
-
32
- // Tolerance on |norm - 1| for pose quaternions, and on orthonormality /
33
- // determinant for emitted matrices. Float32-serialized source data is off by
34
- // ~1e-7 at worst, so 1e-6 is comfortably above input noise while still
35
- // catching real corruption.
36
- const UNIT_TOLERANCE = 1e-6;
37
-
38
- const IDENTITY = [
39
- [1, 0, 0],
40
- [0, 1, 0],
41
- [0, 0, 1],
42
- ];
43
-
44
- const SOURCE_BY_TARGET = new Map(
45
- COZYCLAY_BONES.map((source) => [
46
- CSKEL27_JOINTS[COZYCLAY_TO_CSKEL27[source]],
47
- source,
48
- ])
49
- );
50
-
51
- const CANONICAL_ROOT_Y = -Math.min(...CSKEL27_NEUTRAL.map((joint) => joint[1]));
52
-
53
- /** Floor-aligned CoreSkeleton27 reference used when no clip reference is
54
- * supplied. A generated motion is not a skeleton definition: borrowing its
55
- * frame-zero root made a rolling clip lower every authored pose by 10 cm.
56
- * The neutral skeleton is stable, deterministic, and keeps both toes at Y=0. */
57
- export function canonicalCskel27Reference() {
58
- return {
59
- local_rot_mats: CSKEL27_JOINTS.map(() => IDENTITY.map((row) => row.slice())),
60
- posed_joints: CSKEL27_NEUTRAL.map(([x, y, z]) => [x, y + CANONICAL_ROOT_Y, z]),
61
- };
62
- }
63
-
64
- function isFiniteNumber(value) {
65
- return typeof value === "number" && Number.isFinite(value);
66
- }
67
-
68
- function determinant3(m) {
69
- return (
70
- m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
71
- m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +
72
- m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0])
73
- );
74
- }
75
-
76
- function requireUnitQuaternion(q, bone) {
77
- if (!Array.isArray(q) || q.length !== 4 || !q.every(isFiniteNumber)) {
78
- throw new Error(
79
- `poseToCskel27: bone "${bone}" is not a [w, x, y, z] quaternion of four finite numbers`
80
- );
81
- }
82
- const norm = Math.hypot(q[0], q[1], q[2], q[3]);
83
- if (Math.abs(norm - 1) > UNIT_TOLERANCE) {
84
- throw new Error(
85
- `poseToCskel27: bone "${bone}" is not a unit quaternion (norm ${norm})`
86
- );
87
- }
88
- }
89
-
90
- // A matrix must stay inside the rotation group: rows orthonormal (unit
91
- // length, pairwise orthogonal) and right-handed.
92
- function requireRotationMatrix(m, label) {
93
- for (let i = 0; i < 3; i += 1) {
94
- const row = m[i];
95
- const normSq = row[0] * row[0] + row[1] * row[1] + row[2] * row[2];
96
- if (Math.abs(normSq - 1) > UNIT_TOLERANCE) {
97
- throw new Error(
98
- `poseToCskel27: ${label} is not orthonormal (row ${i} has squared length ${normSq})`
99
- );
100
- }
101
- for (let j = i + 1; j < 3; j += 1) {
102
- const other = m[j];
103
- const dot = row[0] * other[0] + row[1] * other[1] + row[2] * other[2];
104
- if (Math.abs(dot) > UNIT_TOLERANCE) {
105
- throw new Error(
106
- `poseToCskel27: ${label} is not orthonormal (rows ${i} and ${j} dot to ${dot})`
107
- );
108
- }
109
- }
110
- }
111
- const det = determinant3(m);
112
- if (Math.abs(det - 1) > UNIT_TOLERANCE) {
113
- throw new Error(`poseToCskel27: ${label} has determinant ${det}, not +1`);
114
- }
115
- }
116
-
117
- /**
118
- * Convert a CozyClayPoseV1 into the frame arrays the ARDY generator expects.
119
- * `rest` is the parsed public/ardy/cskel27-rest.json, `reference` a parsed
120
- * ardy.frame.v1 fixture from the base motion the pose will constrain.
121
- * Returns { local_rot_mats, posed_joints, filled_identity }.
122
- */
123
- export function poseToCskel27({ pose, rest, reference }) {
124
- if (!pose || typeof pose !== "object") {
125
- throw new Error(
126
- `poseToCskel27: pose is ${pose === null ? "null" : typeof pose}, expected an object`
127
- );
128
- }
129
- if (pose.schema !== "cozyclay.pose.v1") {
130
- throw new Error(
131
- `poseToCskel27: unsupported pose schema ${JSON.stringify(pose.schema)} — expected "cozyclay.pose.v1"`
132
- );
133
- }
134
- if (!pose.bones || typeof pose.bones !== "object" || Array.isArray(pose.bones)) {
135
- throw new Error("poseToCskel27: pose.bones must be an object keyed by mixamo bone name");
136
- }
137
- if (pose.root !== undefined) {
138
- if (!Array.isArray(pose.root) || pose.root.length !== 3 || !pose.root.every(isFiniteNumber)) {
139
- throw new Error("poseToCskel27: pose.root must be [x, y, z] finite metres when present");
140
- }
141
- }
142
-
143
- for (const bone of COZYCLAY_BONES) {
144
- if (!(bone in pose.bones)) {
145
- throw new Error(`poseToCskel27: pose.bones is missing "${bone}"`);
146
- }
147
- requireUnitQuaternion(pose.bones[bone], bone);
148
- }
149
-
150
- if (!rest || !Array.isArray(rest.joints)) {
151
- throw new Error("poseToCskel27: rest must be parsed cskel27-rest.json with a joints array");
152
- }
153
- const restByJoint = new Map();
154
- for (const entry of rest.joints) {
155
- if (!entry || typeof entry.name !== "string") {
156
- throw new Error("poseToCskel27: rest.joints entries must carry a string name");
157
- }
158
- if (entry.rest !== null) {
159
- if (
160
- !Array.isArray(entry.rest) ||
161
- entry.rest.length !== 3 ||
162
- !entry.rest.every(
163
- (row) => Array.isArray(row) && row.length === 3 && row.every(isFiniteNumber)
164
- )
165
- ) {
166
- throw new Error(
167
- `poseToCskel27: rest for "${entry.name}" is neither null nor a 3x3 finite matrix`
168
- );
169
- }
170
- }
171
- restByJoint.set(entry.name, entry.rest);
172
- }
173
-
174
- const local_rot_mats = new Array(CSKEL27_JOINTS.length);
175
- const filled_identity = [];
176
- const rotation_constraint_indices = [];
177
- for (let index = 0; index < CSKEL27_JOINTS.length; index += 1) {
178
- const name = CSKEL27_JOINTS[index];
179
- const sourceName = SOURCE_BY_TARGET.get(name);
180
- const rb = sourceName ? restByJoint.get(sourceName) : null;
181
- if (sourceName && rb !== null && rb !== undefined) {
182
- // L = Rb @ basis @ Rb^T; basisQuaternionToLocalRotation is the
183
- // quatToMat + basisToLocal composition from convert.js.
184
- local_rot_mats[index] = basisQuaternionToLocalRotation(
185
- pose.bones[sourceName],
186
- rb
187
- );
188
- rotation_constraint_indices.push(index);
189
- } else {
190
- // Fresh identity per joint so callers can never alias a shared
191
- // constant by mutating one row.
192
- local_rot_mats[index] = IDENTITY.map((row) => row.slice());
193
- filled_identity.push({
194
- joint: name,
195
- reason: sourceName ? "no rest rotation" : "not authored",
196
- });
197
- }
198
- }
199
-
200
- for (let index = 0; index < CSKEL27_JOINTS.length; index += 1) {
201
- requireRotationMatrix(
202
- local_rot_mats[index],
203
- `${CSKEL27_JOINTS[index]} (local_rot_mats[${index}])`
204
- );
205
- }
206
-
207
- // A reference may still supply different skeleton proportions, but its
208
- // frame-zero root is never copied. Placement is authored explicitly in
209
- // pose.root; otherwise the canonical floor-aligned neutral root is used.
210
- // This decouples body shape from whichever motion happened to be selected.
211
- const skeleton = reference ?? canonicalCskel27Reference();
212
- if (!Array.isArray(skeleton.posed_joints) || !Array.isArray(skeleton.local_rot_mats)) {
213
- throw new Error("poseToCskel27: reference must carry posed_joints and local_rot_mats");
214
- }
215
- const offsets = deriveBoneOffsets(skeleton.posed_joints, skeleton.local_rot_mats);
216
- const canonicalRoot = canonicalCskel27Reference().posed_joints[0];
217
- const posed_joints = forwardKinematics(local_rot_mats, offsets, pose.root ?? canonicalRoot);
218
-
219
- return {
220
- local_rot_mats,
221
- posed_joints,
222
- filled_identity,
223
- rotation_constraint_indices,
224
- };
225
- }
package/src/ardy/trim.js DELETED
@@ -1,33 +0,0 @@
1
- // trim.js — cut a loaded take to a frame range. The slice is a NEW motion
2
- // object in the exact npz-decoded shape; the caller keeps the original, so
3
- // trimming is non-destructive and re-trimming always cuts from the full
4
- // take. Frame 0 of the slice becomes the playback anchor: applyMotionFrame
5
- // re-anchors X/Z on the anchor frame, so a mid-clip cut plays at the
6
- // character's placement instead of teleporting to the original frame 0.
7
- // The spread carries every non-array field with the slice — `personScale`
8
- // included: a cut is the same performer, and a take that lost its stature
9
- // mid-edit would replay the remaining frames at the wrong stride length.
10
-
11
- import { CSKEL27_JOINTS } from "./cskel27.js";
12
-
13
- export function sliceMotion(motion, startFrame, endFrame) {
14
- if (!motion || !Number.isInteger(motion.frames) || motion.frames < 1) {
15
- throw new Error("sliceMotion: motion.frames must be a positive integer");
16
- }
17
- if (!Number.isInteger(startFrame) || !Number.isInteger(endFrame)) {
18
- throw new Error("sliceMotion: startFrame and endFrame must be integers");
19
- }
20
- if (startFrame < 0 || endFrame >= motion.frames || startFrame > endFrame) {
21
- throw new Error(`sliceMotion: range ${startFrame}..${endFrame} is outside 0..${motion.frames - 1}`);
22
- }
23
- const joints = CSKEL27_JOINTS.length;
24
- const frames = endFrame - startFrame + 1;
25
- return {
26
- ...motion,
27
- frames,
28
- rotMats: motion.rotMats.slice(startFrame * joints * 9, (endFrame + 1) * joints * 9),
29
- rootPos: motion.rootPos.slice(startFrame * 3, (endFrame + 1) * 3),
30
- posedJoints: motion.posedJoints.slice(startFrame * joints * 3, (endFrame + 1) * joints * 3),
31
- anchorFrame: 0,
32
- };
33
- }