cozyclay 2.1.0 → 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 (583) hide show
  1. package/CHANGELOG.md +65 -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 +22 -6
  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-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-BSesrCpL.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/llms.txt +14 -0
  40. package/dist/sw.js +3 -6
  41. package/dist/workflow/index.html +5 -4
  42. package/mcp/LIVE-PROTOCOL.md +7 -47
  43. package/mcp/README.md +16 -26
  44. package/mcp/live-hub.mjs +6 -10
  45. package/mcp/package.json +1 -3
  46. package/mcp/tool-handlers.mjs +4 -168
  47. package/package.json +3 -22
  48. package/src/App.jsx +174 -2639
  49. package/src/agent-progress.js +79 -0
  50. package/src/agent-turn-mark.js +30 -0
  51. package/src/analytics.js +1 -19
  52. package/src/app-context.js +5 -0
  53. package/src/app-stage.jsx +2 -34
  54. package/src/asset-pane.jsx +6 -5
  55. package/src/camera-block.js +21 -0
  56. package/src/camera-direction.js +120 -0
  57. package/src/character-kind.js +3 -9
  58. package/src/command-bus.js +8 -6
  59. package/src/commands/cast.js +5 -34
  60. package/src/commands/elements/character.js +1 -1
  61. package/src/commands/elements/motion.js +1 -6
  62. package/src/commands/elements/object.js +6 -2
  63. package/src/commands/elements/shot.js +4 -1
  64. package/src/commands/elements.js +38 -14
  65. package/src/commands/index.js +3 -1
  66. package/src/commands/kits.js +37 -0
  67. package/src/commands/motion-timing.js +57 -0
  68. package/src/commands/motion.js +9 -152
  69. package/src/commands/motion3-compile.js +65 -0
  70. package/src/commands/motion3.js +207 -0
  71. package/src/commands/objects.js +6 -4
  72. package/src/commands/shot.js +49 -11
  73. package/src/commands/stage.js +14 -1
  74. package/src/commands/view.js +4 -1
  75. package/src/document-mirrors.js +42 -0
  76. package/src/document-store.js +4 -0
  77. package/src/domains/cast.js +19 -194
  78. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  79. package/src/domains/motion/take-source.js +51 -0
  80. package/src/domains/motion.js +60 -1838
  81. package/src/domains/scenes.js +12 -55
  82. package/src/domains/shots.js +2 -2
  83. package/src/domains/stage.js +4 -2
  84. package/src/draft-ghost.js +46 -0
  85. package/src/draft-ghost.jsx +129 -0
  86. package/src/dualview.jsx +4 -3
  87. package/src/effects/EffectsLayer.jsx +112 -0
  88. package/src/effects/effect-meshes.js +232 -0
  89. package/src/effects/effect-record.js +103 -0
  90. package/src/effects/emitter.js +59 -0
  91. package/src/effects/simulate.js +261 -0
  92. package/src/effects/state.js +59 -0
  93. package/src/execution-telemetry.js +2 -3
  94. package/src/first-success-guide.jsx +5 -5
  95. package/src/ghost-set.js +257 -0
  96. package/src/held-object-edit.jsx +113 -0
  97. package/src/held-object-pose.js +175 -0
  98. package/src/hierarchy-model.js +1 -1
  99. package/src/hierarchy-panel.jsx +1 -1
  100. package/src/imported-mesh.jsx +103 -0
  101. package/src/kits/held.js +84 -0
  102. package/src/kits/index.js +70 -0
  103. package/src/kits/smoking.js +57 -0
  104. package/src/light-blockers.js +93 -0
  105. package/src/motion/beat-board-model.js +84 -0
  106. package/src/motion/beat-board.css +124 -0
  107. package/src/motion/beat-board.jsx +59 -0
  108. package/src/motion/center-of-mass.js +66 -0
  109. package/src/motion/fix-collisions.js +850 -0
  110. package/src/motion/physics-review.js +118 -0
  111. package/src/{ardy → motion}/physics-support.js +1 -76
  112. package/src/motion/rig-snapshot.js +22 -0
  113. package/src/motion/take-segments.jsx +140 -0
  114. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  115. package/src/{ardy → motion}/timeline.css +1 -2
  116. package/src/{ardy → motion}/timeline.jsx +48 -419
  117. package/src/motion/waypoints.js +76 -0
  118. package/src/motion3/beats.js +83 -0
  119. package/src/motion3/body.js +158 -0
  120. package/src/motion3/bones.js +47 -0
  121. package/src/motion3/carried.js +47 -0
  122. package/src/motion3/compile-job.js +75 -0
  123. package/src/motion3/compile-worker.js +10 -0
  124. package/src/motion3/compiler/anchors.js +105 -0
  125. package/src/motion3/compiler/arm-orient.js +128 -0
  126. package/src/motion3/compiler/channels.js +125 -0
  127. package/src/motion3/compiler/compile.js +205 -0
  128. package/src/motion3/compiler/gait-rhythm.js +97 -0
  129. package/src/motion3/compiler/grip.js +171 -0
  130. package/src/motion3/compiler/head-steady.js +48 -0
  131. package/src/motion3/compiler/hold.js +134 -0
  132. package/src/motion3/compiler/idle.js +113 -0
  133. package/src/motion3/compiler/limbs.js +170 -0
  134. package/src/motion3/compiler/math.js +72 -0
  135. package/src/motion3/compiler/pose.js +162 -0
  136. package/src/motion3/compiler/quat.js +49 -0
  137. package/src/motion3/compiler/skeleton.js +74 -0
  138. package/src/motion3/compiler/validate-common.js +32 -0
  139. package/src/motion3/compiler/validate-goals.js +118 -0
  140. package/src/motion3/compiler/validate-objects.js +143 -0
  141. package/src/motion3/compiler/validate-parts.js +116 -0
  142. package/src/motion3/compiler/validate.js +122 -0
  143. package/src/motion3/compiler/vocab.js +73 -0
  144. package/src/motion3/compiler/walk-pelvis.js +275 -0
  145. package/src/motion3/compiler/walk.js +207 -0
  146. package/src/motion3/compiler/wrist-clamp.js +32 -0
  147. package/src/motion3/delta.js +47 -0
  148. package/src/motion3/describe.js +174 -0
  149. package/src/motion3/docs.js +27 -0
  150. package/src/motion3/edit-carry.js +21 -0
  151. package/src/motion3/fix/ease.js +16 -0
  152. package/src/motion3/fix/ground.js +37 -0
  153. package/src/motion3/fix/index.js +52 -0
  154. package/src/motion3/fix/push.js +71 -0
  155. package/src/motion3/fix/reach.js +46 -0
  156. package/src/motion3/fix/retime.js +79 -0
  157. package/src/motion3/fix/self.js +211 -0
  158. package/src/motion3/fix/slide.js +70 -0
  159. package/src/motion3/fix/turn.js +51 -0
  160. package/src/motion3/follow.js +39 -0
  161. package/src/motion3/free-motion.js +173 -0
  162. package/src/motion3/grip-choice.js +130 -0
  163. package/src/motion3/hold-plan.js +157 -0
  164. package/src/motion3/json-patch.js +77 -0
  165. package/src/motion3/key-aim.js +105 -0
  166. package/src/motion3/key-edit.js +82 -0
  167. package/src/motion3/lenient.js +127 -0
  168. package/src/motion3/object-keys.js +236 -0
  169. package/src/motion3/object-pose.js +182 -0
  170. package/src/motion3/object-tracks.js +12 -0
  171. package/src/motion3/pipeline.js +102 -0
  172. package/src/motion3/playback.js +51 -0
  173. package/src/motion3/probes.js +91 -0
  174. package/src/motion3/qa/body-checks.js +34 -0
  175. package/src/motion3/qa/check-names.js +14 -0
  176. package/src/motion3/qa/checks.js +121 -0
  177. package/src/motion3/qa/contact-checks.js +51 -0
  178. package/src/motion3/qa/explain.js +80 -0
  179. package/src/motion3/qa/fmt.js +5 -0
  180. package/src/motion3/qa/foot-checks.js +72 -0
  181. package/src/motion3/qa/geometry.js +77 -0
  182. package/src/motion3/qa/goals.js +191 -0
  183. package/src/motion3/qa/ground.js +60 -0
  184. package/src/motion3/qa/hints-contact.js +179 -0
  185. package/src/motion3/qa/hints-goal.js +160 -0
  186. package/src/motion3/qa/hints-knee.js +24 -0
  187. package/src/motion3/qa/hints-motion.js +209 -0
  188. package/src/motion3/qa/hints-object.js +91 -0
  189. package/src/motion3/qa/index.js +42 -0
  190. package/src/motion3/qa/key-checks.js +82 -0
  191. package/src/motion3/qa/near.js +96 -0
  192. package/src/motion3/qa/object-checks.js +135 -0
  193. package/src/motion3/qa/patch.js +161 -0
  194. package/src/motion3/qa/severity.js +38 -0
  195. package/src/motion3/qa/spec-checks.js +65 -0
  196. package/src/motion3/qa/style.js +218 -0
  197. package/src/motion3/qa/wrist-checks.js +69 -0
  198. package/src/motion3/qa/wrist-obs.js +60 -0
  199. package/src/motion3/refs.js +120 -0
  200. package/src/motion3/repair-tune.js +121 -0
  201. package/src/motion3/repair.js +83 -0
  202. package/src/motion3/report.js +67 -0
  203. package/src/motion3/rigs/index.js +14 -0
  204. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  205. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  207. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  208. package/src/motion3/scene.js +60 -0
  209. package/src/motion3/schema/brief.js +89 -0
  210. package/src/motion3/schema/fields.js +44 -0
  211. package/src/motion3/schema/spec-examples.js +46 -0
  212. package/src/motion3/schema/topics.js +111 -0
  213. package/src/motion3/schema/types.js +147 -0
  214. package/src/motion3/search.js +117 -0
  215. package/src/motion3/second-hand.js +112 -0
  216. package/src/motion3/skills/basic.js +82 -0
  217. package/src/motion3/skills/book.js +76 -0
  218. package/src/motion3/skills/car.js +145 -0
  219. package/src/motion3/skills/frames-auto.js +29 -0
  220. package/src/motion3/skills/index.js +83 -0
  221. package/src/motion3/skills/info.js +65 -0
  222. package/src/motion3/skills/smoke-kit.js +109 -0
  223. package/src/motion3/skills/smoke.js +160 -0
  224. package/src/motion3/spec-store.js +59 -0
  225. package/src/motion3/take-edit.js +155 -0
  226. package/src/motion3/take.js +63 -0
  227. package/src/motion3/timeline.js +127 -0
  228. package/src/motion3/views.js +121 -0
  229. package/src/motion3/walk-plan.js +119 -0
  230. package/src/object-catalog.jsx +7 -1
  231. package/src/object-colors.js +98 -0
  232. package/src/object-gizmo-parts.js +115 -0
  233. package/src/object-gizmo.jsx +37 -122
  234. package/src/object-glow.js +139 -0
  235. package/src/object-hidden.js +33 -0
  236. package/src/object-look.js +196 -0
  237. package/src/object-size.js +10 -0
  238. package/src/object-travel.js +71 -6
  239. package/src/panels/CameraPanel.jsx +7 -7
  240. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  241. package/src/panels/LightPanel.jsx +25 -4
  242. package/src/panels/ObjectLookPanel.jsx +88 -0
  243. package/src/panels/PoseImagePanel.jsx +1 -1
  244. package/src/panels/PosePanel.jsx +2 -17
  245. package/src/panels/RigControlPanel.jsx +5 -53
  246. package/src/panels/SubjectBox.jsx +4 -1
  247. package/src/panels/details.css +14 -0
  248. package/src/posestudio.jsx +4 -27
  249. package/src/project-browser.jsx +3 -4
  250. package/src/project-resources.js +18 -31
  251. package/src/project.js +13 -104
  252. package/src/props.jsx +25 -280
  253. package/src/rail-dot-drag.js +23 -0
  254. package/src/render-passes.js +10 -0
  255. package/src/resource-status.jsx +1 -0
  256. package/src/result-modal.jsx +4 -19
  257. package/src/room.jsx +20 -12
  258. package/src/scene-assets.js +8 -6
  259. package/src/scene-light-place.js +72 -0
  260. package/src/scene-lights.jsx +148 -0
  261. package/src/scene-objects.js +31 -139
  262. package/src/scenes.js +15 -105
  263. package/src/semantic-edit.js +2 -5
  264. package/src/set-pieces.jsx +183 -0
  265. package/src/settings-menu.jsx +3 -11
  266. package/src/shell/BottomDock.jsx +11 -53
  267. package/src/shell/CompositionGuideButton.jsx +20 -0
  268. package/src/shell/DetailsSlot.jsx +16 -200
  269. package/src/shell/GhostsMenuGroup.jsx +74 -0
  270. package/src/shell/LibrarySlot.jsx +1 -3
  271. package/src/shell/MenuBar.jsx +3 -3
  272. package/src/shell/PreferencesDialog.jsx +15 -264
  273. package/src/shell/PreferencesSlot.jsx +2 -8
  274. package/src/shell/ShotPreviewHeader.jsx +17 -0
  275. package/src/shell/TopBar.jsx +5 -83
  276. package/src/shell/ViewportToolbar.jsx +23 -93
  277. package/src/shell/agent-glass.css +19 -6
  278. package/src/shell/details-selection.js +42 -0
  279. package/src/shell/ghosts-menu.css +22 -0
  280. package/src/shell/glass-regions.css +29 -3
  281. package/src/shell/preferences.css +6 -1
  282. package/src/shell/viewport.css +12 -0
  283. package/src/shot-authoring.js +4 -7
  284. package/src/soft-shadows.js +37 -0
  285. package/src/stage-attach-frames.js +12 -12
  286. package/src/stage-canvas-rigs.jsx +3 -3
  287. package/src/stage-capture.jsx +42 -8
  288. package/src/stage-characters.jsx +22 -216
  289. package/src/stage-editor-gizmos.jsx +6 -6
  290. package/src/stage-environment.js +93 -0
  291. package/src/stage-hdr-builtins.js +107 -0
  292. package/src/stage-hdr-image.js +116 -0
  293. package/src/stage-hdr-library.js +70 -0
  294. package/src/stage-hdr-map.js +94 -0
  295. package/src/stage-hdr.js +130 -0
  296. package/src/stage-lighting.js +149 -0
  297. package/src/stage-occlusion.js +210 -0
  298. package/src/stage-sky.jsx +159 -0
  299. package/src/stage-startup-defaults.js +5 -9
  300. package/src/studio-actions.js +12 -14
  301. package/src/studio-agent-commands.js +46 -16
  302. package/src/studio-agent-motion.js +9 -9
  303. package/src/studio-agent-protocol.js +46 -73
  304. package/src/studio-app-binding.js +29 -45
  305. package/src/studio-asset-list.js +17 -0
  306. package/src/studio-contact-sheet.js +37 -5
  307. package/src/studio-elements.js +27 -7
  308. package/src/studio-entity-bounds.js +18 -0
  309. package/src/studio-error-codes.js +8 -0
  310. package/src/studio-export-framing.js +152 -0
  311. package/src/studio-lighting-check.js +103 -0
  312. package/src/studio-motion-visual.js +150 -0
  313. package/src/studio-schema-errors.js +80 -0
  314. package/src/studio-support-gap.js +74 -0
  315. package/src/styles.css +1 -19
  316. package/src/timeline-defaults.js +5 -0
  317. package/src/timeline-extent.js +8 -20
  318. package/src/tutorial-walk.js +17 -0
  319. package/src/ui-scrub.js +1 -1
  320. package/src/use-shot-camera-tracks.js +12 -0
  321. package/src/view-ghosts.js +97 -0
  322. package/src/view-ghosts.jsx +49 -0
  323. package/src/workflow/AgentPanel.jsx +47 -166
  324. package/src/workflow/AgentProgressCard.jsx +107 -0
  325. package/src/workflow/AgentReplyText.jsx +37 -0
  326. package/src/workflow/AgentTurnSteps.jsx +84 -0
  327. package/src/workflow/LoginPanel.jsx +140 -0
  328. package/src/workflow/WorkflowBuilder.jsx +7 -23
  329. package/src/workflow/agent-client.js +54 -51
  330. package/src/workflow/agent-panel.css +71 -1
  331. package/src/workflow/agent-progress-card.css +167 -0
  332. package/src/workflow/agent-progress-view.js +47 -0
  333. package/src/workflow/agent-turn-steps.css +113 -0
  334. package/src/workflow/agent-turn.js +191 -0
  335. package/src/workflow/login-client.js +34 -0
  336. package/src/workflow/motion-input.js +18 -31
  337. package/src/workflow/node-schema.js +1 -1
  338. package/src/workflow/reply-markdown.js +69 -0
  339. package/src/workflow/scene-asset-sync.js +8 -8
  340. package/tools/agent-session-stats.mjs +61 -0
  341. package/tools/dev-full.mjs +5 -56
  342. package/tools/eslint-baseline.json +12 -13
  343. package/tools/headless-studio.mjs +85 -0
  344. package/tools/knip-baseline.json +0 -179
  345. package/tools/loc-baseline.json +33 -83
  346. package/tools/motion3/extract-body.mjs +103 -0
  347. package/tools/motion3/extract-rig.mjs +85 -0
  348. package/tools/process-supervisor.mjs +0 -88
  349. package/tools/run-tests.mjs +9 -124
  350. package/bin/agent/motion-runtime.mjs +0 -76
  351. package/dist/ardy/cskel27-rest.json +0 -557
  352. package/dist/assets/analytics-B41FmPYI.js +0 -1
  353. package/dist/assets/app-Do-Og5Pu.css +0 -1
  354. package/dist/assets/app-DwP-tl2x.js +0 -4920
  355. package/dist/assets/config-Bx7pYsD9.js +0 -1
  356. package/dist/assets/config-DeoFTYzb.css +0 -1
  357. package/dist/assets/demo-Dt0qZfS7.js +0 -1
  358. package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
  359. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  360. package/dist/assets/ticket-jqMhqL88.js +0 -1
  361. package/dist/assets/workflow-Br-K7Srs.js +0 -179
  362. package/dist/demo/walk-then-stop.npz +0 -0
  363. package/mcp/ardy-prompts.mjs +0 -218
  364. package/src/ardy/auto-fix-panel.css +0 -108
  365. package/src/ardy/auto-physics.js +0 -1194
  366. package/src/ardy/client.js +0 -153
  367. package/src/ardy/convert.js +0 -313
  368. package/src/ardy/cskel27-neutral.js +0 -39
  369. package/src/ardy/cskel27.js +0 -77
  370. package/src/ardy/export.js +0 -165
  371. package/src/ardy/fix-collisions.js +0 -2257
  372. package/src/ardy/foot-lock.js +0 -230
  373. package/src/ardy/motion-calibration.js +0 -118
  374. package/src/ardy/motion-edit.js +0 -213
  375. package/src/ardy/motion-url.js +0 -55
  376. package/src/ardy/mp4-duration.js +0 -102
  377. package/src/ardy/npz.js +0 -595
  378. package/src/ardy/physics-panel.css +0 -21
  379. package/src/ardy/physics-panel.jsx +0 -89
  380. package/src/ardy/physics-refine.js +0 -111
  381. package/src/ardy/physics-review.js +0 -567
  382. package/src/ardy/physics-temporal.js +0 -54
  383. package/src/ardy/platform-fit-panel.css +0 -64
  384. package/src/ardy/platform-fit-panel.jsx +0 -41
  385. package/src/ardy/platform-fit.js +0 -326
  386. package/src/ardy/playback.js +0 -711
  387. package/src/ardy/pose-pin.js +0 -97
  388. package/src/ardy/prompt-clips.js +0 -30
  389. package/src/ardy/retime.js +0 -211
  390. package/src/ardy/root-drop.js +0 -369
  391. package/src/ardy/timeline-resize.js +0 -13
  392. package/src/ardy/to-cskel27.js +0 -225
  393. package/src/ardy/trim.js +0 -33
  394. package/src/ardy/waypoints.js +0 -369
  395. package/src/ardy-bridge-contract.js +0 -281
  396. package/src/domains/motion/motion-video-capture.js +0 -664
  397. package/src/i2v-motion-client.js +0 -77
  398. package/src/i2v-motion-studio.jsx +0 -180
  399. package/src/line-edit.js +0 -1348
  400. package/src/motion/generation.js +0 -105
  401. package/src/motion-readiness-ui.jsx +0 -67
  402. package/src/motion-readiness.js +0 -40
  403. package/src/motion-resources.js +0 -177
  404. package/src/motion-store.js +0 -65
  405. package/src/motion-trail.js +0 -601
  406. package/src/multimodel-ingest.js +0 -394
  407. package/src/panels/PromptBlocksPanel.jsx +0 -444
  408. package/src/panels/VideoCapturePanel.jsx +0 -181
  409. package/src/pose-extract/browser.js +0 -42
  410. package/src/pose-extract/detector.js +0 -100
  411. package/src/pose-extract/fit.js +0 -227
  412. package/src/pose-extract/image-frame.js +0 -51
  413. package/src/pose-extract/index.js +0 -58
  414. package/src/pose-extract/keyframes.js +0 -74
  415. package/src/pose-extract/landmarks.js +0 -162
  416. package/src/pose-extract/mirror.js +0 -153
  417. package/src/pose-extract/take.js +0 -131
  418. package/src/pose-extract/video-frames.js +0 -91
  419. package/src/take-recipe.js +0 -165
  420. package/src/trail-key-conflicts.js +0 -39
  421. package/src/trail-pick.js +0 -59
  422. package/src/use-i2v-capture-modal.js +0 -15
  423. package/tools/ardy/BRIDGE.md +0 -37
  424. package/tools/ardy/GVHMR-NPZ.md +0 -68
  425. package/tools/ardy/README.md +0 -124
  426. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  427. package/tools/ardy/artifacts.mjs +0 -34
  428. package/tools/ardy/bridge.mjs +0 -1732
  429. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  430. package/tools/ardy/cclay_constrained_generate.py +0 -561
  431. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  432. package/tools/ardy/cclay_motion_edit.py +0 -510
  433. package/tools/ardy/cclay_sequence_generate.py +0 -705
  434. package/tools/ardy/cclay_worker.py +0 -304
  435. package/tools/ardy/dump-npz.py +0 -205
  436. package/tools/ardy/extract-rest.mjs +0 -299
  437. package/tools/ardy/extract.mjs +0 -507
  438. package/tools/ardy/footage.mjs +0 -467
  439. package/tools/ardy/gvhmr-floor.mjs +0 -102
  440. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  441. package/tools/ardy/gvhmr_fastpath.py +0 -168
  442. package/tools/ardy/gvhmr_trajectory.py +0 -240
  443. package/tools/ardy/merge-text-encoder.py +0 -160
  444. package/tools/ardy/mocap-metrics.mjs +0 -200
  445. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  446. package/tools/ardy/motion-stabilize.mjs +0 -348
  447. package/tools/ardy/npz.mjs +0 -414
  448. package/tools/ardy/pose-to-npz.mjs +0 -106
  449. package/tools/ardy/prompt-limits.mjs +0 -5
  450. package/tools/ardy/run-edit-on-box.sh +0 -73
  451. package/tools/ardy/run-local.mjs +0 -233
  452. package/tools/ardy/run-on-box.sh +0 -593
  453. package/tools/ardy/run-sequence-on-box.sh +0 -177
  454. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  455. package/tools/ardy/runners/index.mjs +0 -18
  456. package/tools/ardy/runners/local.mjs +0 -455
  457. package/tools/ardy/runners/proc.mjs +0 -125
  458. package/tools/ardy/runners/remote.mjs +0 -252
  459. package/tools/ardy/setup-local.mjs +0 -189
  460. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  461. package/tools/ardy/setup-text-encoder.py +0 -306
  462. package/tools/ardy/smpl-cskel27.mjs +0 -178
  463. package/tools/ardy/visual-qa.mjs +0 -196
  464. package/tools/ardy/vq-car.mjs +0 -52
  465. package/tools/bench/EXP3.md +0 -61
  466. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  467. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  468. package/tools/bench/cclay_bench_runner.py +0 -42
  469. package/tools/bench/cube-contact.mjs +0 -162
  470. package/tools/bench/exp3.mjs +0 -152
  471. package/tools/bench/extract-bench-lib.mjs +0 -216
  472. package/tools/bench/extract-bench.mjs +0 -302
  473. package/tools/bench/fal-generate.mjs +0 -88
  474. package/tools/bench/fit/README.md +0 -189
  475. package/tools/bench/fit/camera.mjs +0 -59
  476. package/tools/bench/fit/contact.mjs +0 -419
  477. package/tools/bench/fit/footlock.mjs +0 -234
  478. package/tools/bench/fit/motion.mjs +0 -85
  479. package/tools/bench/fit/pin.mjs +0 -27
  480. package/tools/bench/fit/remote.mjs +0 -105
  481. package/tools/bench/fit-bench.mjs +0 -126
  482. package/tools/bench/fit-sanity.mjs +0 -45
  483. package/tools/bench/metrics.mjs +0 -313
  484. package/tools/bench/obs/depth.mjs +0 -258
  485. package/tools/bench/obs/extrinsics.mjs +0 -175
  486. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  487. package/tools/bench/obs/ground.mjs +0 -294
  488. package/tools/bench/obs/heading.mjs +0 -151
  489. package/tools/bench/obs/ladder.mjs +0 -555
  490. package/tools/bench/obs/mannequin-betas.json +0 -124
  491. package/tools/bench/obs/remote.mjs +0 -83
  492. package/tools/bench/obs/rest_joints.py +0 -52
  493. package/tools/bench/obs/ybot-targets.mjs +0 -49
  494. package/tools/bench/obs-bench.mjs +0 -520
  495. package/tools/bench/score.mjs +0 -343
  496. package/tools/bench/summarize.mjs +0 -86
  497. package/tools/demo-worker/README.md +0 -137
  498. package/tools/demo-worker/api-client.mjs +0 -233
  499. package/tools/demo-worker/generate.mjs +0 -301
  500. package/tools/demo-worker/index.mjs +0 -466
  501. package/tools/demo-worker/sign-core.mjs +0 -112
  502. package/tools/demo-worker/sign.mjs +0 -161
  503. package/tools/gt-render/browser.mjs +0 -159
  504. package/tools/gt-render/camera-math.mjs +0 -276
  505. package/tools/gt-render/page.mjs +0 -267
  506. package/tools/gt-render/render.mjs +0 -514
  507. package/tools/gt-render/scene-box.mjs +0 -31
  508. package/tools/gt-render/take-transform.mjs +0 -87
  509. package/tools/kimodo/compare-seam.mjs +0 -108
  510. package/tools/kimodo/constraints.mjs +0 -244
  511. package/tools/kimodo/edit.mjs +0 -259
  512. package/tools/kimodo/effector-constraints.mjs +0 -200
  513. package/tools/kimodo/generate.mjs +0 -646
  514. package/tools/kimodo/local-output.mjs +0 -265
  515. package/tools/kimodo/measure-pose.mjs +0 -65
  516. package/tools/kimodo/measure-preserve.mjs +0 -899
  517. package/tools/kimodo/measure-waypoints.mjs +0 -55
  518. package/tools/kimodo/mlx-generate.py +0 -111
  519. package/tools/kimodo/pose-constraints.mjs +0 -248
  520. package/tools/kimodo/preserve-mask.mjs +0 -543
  521. package/tools/kimodo/read-npz.mjs +0 -189
  522. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  523. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  524. package/tools/kimodo/runner.mjs +0 -284
  525. package/tools/kimodo/seam-batch.mjs +0 -77
  526. package/tools/kimodo/setup-local.mjs +0 -30
  527. package/tools/kimodo/setup-on-box.sh +0 -339
  528. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  529. package/tools/morphgs/assets/gen_truth.py +0 -39
  530. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  531. package/tools/morphgs/assets/playback-check.mjs +0 -30
  532. package/tools/morphgs/demo-gate.sh +0 -26
  533. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  534. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  535. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  536. package/tools/morphgs/setup-on-cluster.sh +0 -126
  537. package/tools/projflow/driver.py +0 -1069
  538. package/tools/projflow/generate.mjs +0 -805
  539. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  540. package/tools/projflow/line-edit-job.mjs +0 -547
  541. package/tools/projflow/replay.mjs +0 -452
  542. package/tools/projflow/runner.mjs +0 -269
  543. package/tools/projflow/service.mjs +0 -742
  544. package/tools/track/DESIGN.md +0 -513
  545. package/tools/track/backfill-provenance.mjs +0 -116
  546. package/tools/track/budget.mjs +0 -8
  547. package/tools/track/check-rig.mjs +0 -209
  548. package/tools/track/diagnostics.schema.json +0 -60
  549. package/tools/track/export-rig.mjs +0 -256
  550. package/tools/track/fallback.mjs +0 -7
  551. package/tools/track/fk-parity-fixture.mjs +0 -161
  552. package/tools/track/gate.mjs +0 -349
  553. package/tools/track/masks.mjs +0 -318
  554. package/tools/track/metrics.mjs +0 -201
  555. package/tools/track/publish-obs.mjs +0 -108
  556. package/tools/track/py/check_env.py +0 -61
  557. package/tools/track/py/eval_lr.py +0 -229
  558. package/tools/track/py/lr_viterbi.py +0 -294
  559. package/tools/track/py/masks.py +0 -405
  560. package/tools/track/py/objective.py +0 -382
  561. package/tools/track/py/rig.py +0 -508
  562. package/tools/track/py/scene.py +0 -326
  563. package/tools/track/py/test_joint_indices.py +0 -123
  564. package/tools/track/py/test_lr_viterbi.py +0 -195
  565. package/tools/track/py/test_masks.py +0 -229
  566. package/tools/track/py/test_rig.py +0 -288
  567. package/tools/track/py/test_scene.py +0 -354
  568. package/tools/track/py/test_track.py +0 -328
  569. package/tools/track/py/track.py +0 -411
  570. package/tools/track/remote.mjs +0 -140
  571. package/tools/track/rig-dump.mjs +0 -227
  572. package/tools/track/run-box-tests.mjs +0 -14
  573. package/tools/track/run-box.mjs +0 -168
  574. package/tools/track/setup-box.sh +0 -59
  575. package/tools/track/study-2d.mjs +0 -728
  576. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  577. /package/src/{ardy → motion}/ground.js +0 -0
  578. /package/src/{ardy → motion}/ik-drag.js +0 -0
  579. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  580. /package/src/{ardy → motion}/ik.js +0 -0
  581. /package/src/{ardy → motion}/physics-surface.js +0 -0
  582. /package/src/{ardy → motion}/playback-clock.js +0 -0
  583. /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
- }