cozyclay 2.1.1 → 3.0.1

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 (585) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +43 -116
  4. package/bin/agent/agent-runner.mjs +14 -15
  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/session-store.mjs +2 -2
  14. package/bin/agent/studio-context-budget.mjs +93 -0
  15. package/bin/agent/studio-motion-reference.mjs +23 -0
  16. package/bin/agent/studio-prompt.mjs +1 -1
  17. package/bin/agent/studio-rebase-text.mjs +32 -0
  18. package/bin/agent/studio-rebase.mjs +26 -39
  19. package/bin/agent/studio-tools.mjs +9 -28
  20. package/bin/agent/tool-arguments.mjs +49 -0
  21. package/bin/agent/turn-frames.mjs +66 -0
  22. package/bin/codex-auth.mjs +9 -2
  23. package/bin/cozyclay.mjs +10 -116
  24. package/bin/live/cli.mjs +3 -3
  25. package/bin/mcp-runtime.mjs +2 -12
  26. package/bin/package-signature.mjs +0 -4
  27. package/dist/app/index.html +7 -6
  28. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  29. package/dist/assets/analytics-BWCqdgWA.js +1 -0
  30. package/dist/assets/app-DfTCxaKk.js +5087 -0
  31. package/dist/assets/app-f-fkV5uP.css +1 -0
  32. package/dist/assets/compile-worker-BxKXh07s.js +5 -0
  33. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  34. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-DNO8kv_N.js} +1 -1
  35. package/dist/assets/{landing-ChUvB_zL.js → landing-yfZaJkWc.js} +1 -1
  36. package/dist/assets/scene-asset-sync-U3kS2rvK.js +20 -0
  37. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  38. package/dist/assets/workflow-D78eiKTa.js +179 -0
  39. package/dist/cozyclay-package.json +1 -1
  40. package/dist/index.html +3 -3
  41. package/dist/sw.js +3 -6
  42. package/dist/workflow/index.html +5 -4
  43. package/mcp/LIVE-PROTOCOL.md +7 -47
  44. package/mcp/README.md +16 -26
  45. package/mcp/live-hub.mjs +6 -10
  46. package/mcp/package.json +1 -3
  47. package/mcp/tool-handlers.mjs +4 -168
  48. package/package.json +3 -22
  49. package/src/App.jsx +151 -2625
  50. package/src/agent-progress.js +80 -0
  51. package/src/agent-turn-mark.js +30 -0
  52. package/src/analytics.js +1 -19
  53. package/src/app-context.js +12 -2
  54. package/src/app-stage.jsx +2 -34
  55. package/src/asset-pane.jsx +6 -5
  56. package/src/camera-block.js +21 -0
  57. package/src/camera-direction.js +120 -0
  58. package/src/character-kind.js +3 -9
  59. package/src/command-bus.js +10 -8
  60. package/src/commands/cast.js +5 -34
  61. package/src/commands/elements/character.js +1 -1
  62. package/src/commands/elements/motion.js +1 -6
  63. package/src/commands/elements/object.js +6 -2
  64. package/src/commands/elements/shot.js +4 -1
  65. package/src/commands/elements.js +38 -14
  66. package/src/commands/index.js +3 -1
  67. package/src/commands/kits.js +37 -0
  68. package/src/commands/motion-timing.js +57 -0
  69. package/src/commands/motion.js +9 -152
  70. package/src/commands/motion3-compile.js +65 -0
  71. package/src/commands/motion3.js +214 -0
  72. package/src/commands/objects.js +6 -4
  73. package/src/commands/shot.js +55 -13
  74. package/src/commands/stage.js +14 -1
  75. package/src/commands/view.js +4 -1
  76. package/src/document-mirrors.js +42 -0
  77. package/src/document-store.js +4 -0
  78. package/src/domains/cast.js +19 -194
  79. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  80. package/src/domains/motion/take-source.js +53 -0
  81. package/src/domains/motion.js +60 -1838
  82. package/src/domains/scenes.js +12 -55
  83. package/src/domains/shots.js +2 -2
  84. package/src/domains/stage.js +4 -2
  85. package/src/draft-ghost.js +47 -0
  86. package/src/draft-ghost.jsx +129 -0
  87. package/src/dualview.jsx +4 -3
  88. package/src/effects/EffectsLayer.jsx +112 -0
  89. package/src/effects/effect-meshes.js +232 -0
  90. package/src/effects/effect-record.js +103 -0
  91. package/src/effects/emitter.js +59 -0
  92. package/src/effects/simulate.js +261 -0
  93. package/src/effects/state.js +59 -0
  94. package/src/execution-telemetry.js +2 -3
  95. package/src/first-success-guide.jsx +5 -5
  96. package/src/ghost-set.js +257 -0
  97. package/src/held-object-edit.jsx +113 -0
  98. package/src/held-object-pose.js +175 -0
  99. package/src/hierarchy-model.js +1 -1
  100. package/src/hierarchy-panel.jsx +1 -1
  101. package/src/imported-mesh.jsx +103 -0
  102. package/src/kits/held.js +84 -0
  103. package/src/kits/index.js +70 -0
  104. package/src/kits/smoking.js +57 -0
  105. package/src/light-blockers.js +93 -0
  106. package/src/motion/beat-board-model.js +84 -0
  107. package/src/motion/beat-board.css +124 -0
  108. package/src/motion/beat-board.jsx +60 -0
  109. package/src/motion/center-of-mass.js +66 -0
  110. package/src/motion/fix-collisions.js +850 -0
  111. package/src/motion/physics-review.js +118 -0
  112. package/src/{ardy → motion}/physics-support.js +1 -76
  113. package/src/motion/rig-snapshot.js +22 -0
  114. package/src/motion/take-segments.jsx +140 -0
  115. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  116. package/src/{ardy → motion}/timeline.css +1 -2
  117. package/src/{ardy → motion}/timeline.jsx +42 -413
  118. package/src/motion/waypoints.js +76 -0
  119. package/src/motion3/beats.js +83 -0
  120. package/src/motion3/body.js +158 -0
  121. package/src/motion3/bones.js +47 -0
  122. package/src/motion3/carried.js +47 -0
  123. package/src/motion3/compile-job.js +79 -0
  124. package/src/motion3/compile-worker.js +10 -0
  125. package/src/motion3/compiler/anchors.js +113 -0
  126. package/src/motion3/compiler/arm-orient.js +128 -0
  127. package/src/motion3/compiler/channels.js +125 -0
  128. package/src/motion3/compiler/compile.js +205 -0
  129. package/src/motion3/compiler/gait-rhythm.js +97 -0
  130. package/src/motion3/compiler/grip.js +171 -0
  131. package/src/motion3/compiler/head-steady.js +48 -0
  132. package/src/motion3/compiler/hold.js +134 -0
  133. package/src/motion3/compiler/idle.js +113 -0
  134. package/src/motion3/compiler/limbs.js +197 -0
  135. package/src/motion3/compiler/math.js +72 -0
  136. package/src/motion3/compiler/pose.js +177 -0
  137. package/src/motion3/compiler/quat.js +49 -0
  138. package/src/motion3/compiler/skeleton.js +74 -0
  139. package/src/motion3/compiler/validate-common.js +32 -0
  140. package/src/motion3/compiler/validate-goals.js +118 -0
  141. package/src/motion3/compiler/validate-objects.js +144 -0
  142. package/src/motion3/compiler/validate-parts.js +118 -0
  143. package/src/motion3/compiler/validate.js +122 -0
  144. package/src/motion3/compiler/vocab.js +74 -0
  145. package/src/motion3/compiler/walk-pelvis.js +275 -0
  146. package/src/motion3/compiler/walk.js +207 -0
  147. package/src/motion3/compiler/wrist-clamp.js +32 -0
  148. package/src/motion3/delta.js +47 -0
  149. package/src/motion3/describe.js +177 -0
  150. package/src/motion3/docs.js +27 -0
  151. package/src/motion3/edit-carry.js +21 -0
  152. package/src/motion3/fix/ease.js +16 -0
  153. package/src/motion3/fix/ground.js +37 -0
  154. package/src/motion3/fix/index.js +52 -0
  155. package/src/motion3/fix/push.js +71 -0
  156. package/src/motion3/fix/reach.js +46 -0
  157. package/src/motion3/fix/retime.js +79 -0
  158. package/src/motion3/fix/self.js +211 -0
  159. package/src/motion3/fix/slide.js +70 -0
  160. package/src/motion3/fix/turn.js +51 -0
  161. package/src/motion3/follow.js +39 -0
  162. package/src/motion3/free-motion.js +204 -0
  163. package/src/motion3/grip-choice.js +130 -0
  164. package/src/motion3/hold-plan.js +157 -0
  165. package/src/motion3/json-patch.js +77 -0
  166. package/src/motion3/key-aim.js +105 -0
  167. package/src/motion3/key-edit.js +82 -0
  168. package/src/motion3/lenient.js +127 -0
  169. package/src/motion3/object-keys.js +236 -0
  170. package/src/motion3/object-pose.js +182 -0
  171. package/src/motion3/object-tracks.js +12 -0
  172. package/src/motion3/people.js +82 -0
  173. package/src/motion3/pipeline.js +102 -0
  174. package/src/motion3/playback.js +51 -0
  175. package/src/motion3/probes.js +91 -0
  176. package/src/motion3/qa/body-checks.js +34 -0
  177. package/src/motion3/qa/check-names.js +14 -0
  178. package/src/motion3/qa/checks.js +125 -0
  179. package/src/motion3/qa/contact-checks.js +51 -0
  180. package/src/motion3/qa/explain.js +80 -0
  181. package/src/motion3/qa/fmt.js +5 -0
  182. package/src/motion3/qa/foot-checks.js +72 -0
  183. package/src/motion3/qa/geometry.js +77 -0
  184. package/src/motion3/qa/goals.js +191 -0
  185. package/src/motion3/qa/ground.js +60 -0
  186. package/src/motion3/qa/hints-contact.js +195 -0
  187. package/src/motion3/qa/hints-goal.js +160 -0
  188. package/src/motion3/qa/hints-knee.js +24 -0
  189. package/src/motion3/qa/hints-motion.js +209 -0
  190. package/src/motion3/qa/hints-object.js +91 -0
  191. package/src/motion3/qa/index.js +44 -0
  192. package/src/motion3/qa/key-checks.js +82 -0
  193. package/src/motion3/qa/near.js +96 -0
  194. package/src/motion3/qa/object-checks.js +135 -0
  195. package/src/motion3/qa/patch.js +161 -0
  196. package/src/motion3/qa/people-checks.js +37 -0
  197. package/src/motion3/qa/severity.js +38 -0
  198. package/src/motion3/qa/spec-checks.js +65 -0
  199. package/src/motion3/qa/style.js +228 -0
  200. package/src/motion3/qa/wrist-checks.js +69 -0
  201. package/src/motion3/qa/wrist-obs.js +60 -0
  202. package/src/motion3/refs.js +129 -0
  203. package/src/motion3/repair-tune.js +121 -0
  204. package/src/motion3/repair.js +83 -0
  205. package/src/motion3/report.js +67 -0
  206. package/src/motion3/rigs/index.js +14 -0
  207. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  208. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  209. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  210. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  211. package/src/motion3/scene.js +60 -0
  212. package/src/motion3/schema/brief.js +89 -0
  213. package/src/motion3/schema/fields.js +44 -0
  214. package/src/motion3/schema/spec-examples.js +46 -0
  215. package/src/motion3/schema/topics.js +113 -0
  216. package/src/motion3/schema/types.js +149 -0
  217. package/src/motion3/search.js +117 -0
  218. package/src/motion3/second-hand.js +112 -0
  219. package/src/motion3/settle.js +136 -0
  220. package/src/motion3/skills/basic.js +83 -0
  221. package/src/motion3/skills/book.js +76 -0
  222. package/src/motion3/skills/car.js +145 -0
  223. package/src/motion3/skills/flip.js +200 -0
  224. package/src/motion3/skills/frames-auto.js +29 -0
  225. package/src/motion3/skills/impact.js +109 -0
  226. package/src/motion3/skills/index.js +85 -0
  227. package/src/motion3/skills/info.js +80 -0
  228. package/src/motion3/skills/smoke-kit.js +109 -0
  229. package/src/motion3/skills/smoke.js +160 -0
  230. package/src/motion3/spec-store.js +59 -0
  231. package/src/motion3/take-edit.js +155 -0
  232. package/src/motion3/take.js +63 -0
  233. package/src/motion3/timeline.js +127 -0
  234. package/src/motion3/views.js +121 -0
  235. package/src/motion3/walk-plan.js +119 -0
  236. package/src/object-catalog.jsx +7 -1
  237. package/src/object-colors.js +98 -0
  238. package/src/object-gizmo-parts.js +115 -0
  239. package/src/object-gizmo.jsx +37 -122
  240. package/src/object-glow.js +139 -0
  241. package/src/object-hidden.js +33 -0
  242. package/src/object-look.js +196 -0
  243. package/src/object-size.js +10 -0
  244. package/src/object-travel.js +71 -6
  245. package/src/panels/CameraPanel.jsx +7 -7
  246. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  247. package/src/panels/LightPanel.jsx +25 -4
  248. package/src/panels/ObjectLookPanel.jsx +88 -0
  249. package/src/panels/PosePanel.jsx +2 -17
  250. package/src/panels/RigControlPanel.jsx +5 -53
  251. package/src/panels/SubjectBox.jsx +4 -1
  252. package/src/panels/details.css +14 -0
  253. package/src/posestudio.jsx +4 -27
  254. package/src/project-browser.jsx +3 -4
  255. package/src/project-resources.js +18 -31
  256. package/src/project.js +13 -104
  257. package/src/props.jsx +25 -280
  258. package/src/qa-label.js +25 -0
  259. package/src/rail-dot-drag.js +23 -0
  260. package/src/render-passes.js +10 -0
  261. package/src/resource-status.jsx +1 -0
  262. package/src/result-modal.jsx +4 -19
  263. package/src/room.jsx +20 -12
  264. package/src/scene-assets.js +8 -6
  265. package/src/scene-light-place.js +72 -0
  266. package/src/scene-lights.jsx +148 -0
  267. package/src/scene-objects.js +31 -139
  268. package/src/scenes.js +15 -105
  269. package/src/semantic-edit.js +2 -5
  270. package/src/set-pieces.jsx +183 -0
  271. package/src/settings-menu.jsx +3 -11
  272. package/src/shell/BottomDock.jsx +9 -51
  273. package/src/shell/DetailsSlot.jsx +16 -200
  274. package/src/shell/GhostsMenuGroup.jsx +74 -0
  275. package/src/shell/LibrarySlot.jsx +1 -3
  276. package/src/shell/MenuBar.jsx +3 -3
  277. package/src/shell/PreferencesDialog.jsx +15 -264
  278. package/src/shell/PreferencesSlot.jsx +2 -8
  279. package/src/shell/TopBar.jsx +5 -84
  280. package/src/shell/ViewportToolbar.jsx +10 -70
  281. package/src/shell/agent-glass.css +19 -6
  282. package/src/shell/details-selection.js +42 -0
  283. package/src/shell/ghosts-menu.css +22 -0
  284. package/src/shell/glass-regions.css +29 -3
  285. package/src/shell/preferences.css +6 -1
  286. package/src/shot-authoring.js +4 -7
  287. package/src/soft-shadows.js +37 -0
  288. package/src/stage-attach-frames.js +12 -12
  289. package/src/stage-canvas-rigs.jsx +3 -3
  290. package/src/stage-capture.jsx +42 -8
  291. package/src/stage-characters.jsx +22 -216
  292. package/src/stage-editor-gizmos.jsx +6 -6
  293. package/src/stage-environment.js +93 -0
  294. package/src/stage-hdr-builtins.js +107 -0
  295. package/src/stage-hdr-image.js +116 -0
  296. package/src/stage-hdr-library.js +70 -0
  297. package/src/stage-hdr-map.js +94 -0
  298. package/src/stage-hdr.js +130 -0
  299. package/src/stage-lighting.js +149 -0
  300. package/src/stage-occlusion.js +210 -0
  301. package/src/stage-sky.jsx +159 -0
  302. package/src/stage-startup-defaults.js +5 -9
  303. package/src/studio-actions.js +16 -14
  304. package/src/studio-agent-commands.js +19 -16
  305. package/src/studio-agent-motion.js +9 -9
  306. package/src/studio-agent-protocol.js +47 -77
  307. package/src/studio-app-binding.js +27 -47
  308. package/src/studio-asset-list.js +17 -0
  309. package/src/studio-contact-sheet.js +37 -5
  310. package/src/studio-elements.js +27 -7
  311. package/src/studio-entity-bounds.js +18 -0
  312. package/src/studio-error-codes.js +15 -0
  313. package/src/studio-export-framing.js +152 -0
  314. package/src/studio-lighting-check.js +103 -0
  315. package/src/studio-motion-visual.js +150 -0
  316. package/src/studio-schema-errors.js +80 -0
  317. package/src/studio-support-gap.js +74 -0
  318. package/src/styles.css +1 -19
  319. package/src/timeline-defaults.js +5 -0
  320. package/src/timeline-extent.js +8 -20
  321. package/src/tutorial-walk.js +17 -0
  322. package/src/ui-scrub.js +1 -1
  323. package/src/use-shot-camera-tracks.js +12 -0
  324. package/src/view-ghosts.js +97 -0
  325. package/src/view-ghosts.jsx +49 -0
  326. package/src/workflow/AgentPanel.jsx +47 -166
  327. package/src/workflow/AgentProgressCard.jsx +109 -0
  328. package/src/workflow/AgentReplyText.jsx +37 -0
  329. package/src/workflow/AgentTurnSteps.jsx +84 -0
  330. package/src/workflow/LoginPanel.jsx +140 -0
  331. package/src/workflow/WorkflowBuilder.jsx +7 -23
  332. package/src/workflow/agent-client.js +54 -51
  333. package/src/workflow/agent-panel.css +71 -1
  334. package/src/workflow/agent-progress-card.css +167 -0
  335. package/src/workflow/agent-progress-view.js +47 -0
  336. package/src/workflow/agent-turn-steps.css +113 -0
  337. package/src/workflow/agent-turn.js +191 -0
  338. package/src/workflow/login-client.js +34 -0
  339. package/src/workflow/motion-input.js +18 -31
  340. package/src/workflow/node-schema.js +1 -1
  341. package/src/workflow/reply-markdown.js +69 -0
  342. package/src/workflow/scene-asset-sync.js +8 -8
  343. package/tools/agent-session-stats.mjs +61 -0
  344. package/tools/dev-full.mjs +5 -56
  345. package/tools/eslint-baseline.json +12 -13
  346. package/tools/knip-baseline.json +0 -179
  347. package/tools/loc-baseline.json +31 -81
  348. package/tools/motion3/extract-body.mjs +103 -0
  349. package/tools/motion3/extract-rig.mjs +85 -0
  350. package/tools/process-supervisor.mjs +0 -88
  351. package/tools/run-tests.mjs +9 -125
  352. package/bin/agent/motion-runtime.mjs +0 -76
  353. package/dist/ardy/cskel27-rest.json +0 -557
  354. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  355. package/dist/assets/app-B_2XB9rw.css +0 -1
  356. package/dist/assets/app-DAuvKPP8.js +0 -4920
  357. package/dist/assets/config-Bx7pYsD9.js +0 -1
  358. package/dist/assets/config-DeoFTYzb.css +0 -1
  359. package/dist/assets/demo-CvKuBgy5.js +0 -1
  360. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  361. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  362. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  363. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  364. package/dist/demo/walk-then-stop.npz +0 -0
  365. package/mcp/ardy-prompts.mjs +0 -218
  366. package/src/ardy/auto-fix-panel.css +0 -108
  367. package/src/ardy/auto-physics.js +0 -1194
  368. package/src/ardy/client.js +0 -153
  369. package/src/ardy/convert.js +0 -313
  370. package/src/ardy/cskel27-neutral.js +0 -39
  371. package/src/ardy/cskel27.js +0 -77
  372. package/src/ardy/export.js +0 -165
  373. package/src/ardy/fix-collisions.js +0 -2257
  374. package/src/ardy/foot-lock.js +0 -230
  375. package/src/ardy/motion-calibration.js +0 -118
  376. package/src/ardy/motion-edit.js +0 -213
  377. package/src/ardy/motion-url.js +0 -55
  378. package/src/ardy/mp4-duration.js +0 -102
  379. package/src/ardy/npz.js +0 -595
  380. package/src/ardy/physics-panel.css +0 -21
  381. package/src/ardy/physics-panel.jsx +0 -89
  382. package/src/ardy/physics-refine.js +0 -111
  383. package/src/ardy/physics-review.js +0 -567
  384. package/src/ardy/physics-temporal.js +0 -54
  385. package/src/ardy/platform-fit-panel.css +0 -64
  386. package/src/ardy/platform-fit-panel.jsx +0 -41
  387. package/src/ardy/platform-fit.js +0 -326
  388. package/src/ardy/playback.js +0 -711
  389. package/src/ardy/pose-pin.js +0 -97
  390. package/src/ardy/prompt-clips.js +0 -30
  391. package/src/ardy/retime.js +0 -211
  392. package/src/ardy/root-drop.js +0 -369
  393. package/src/ardy/timeline-resize.js +0 -13
  394. package/src/ardy/to-cskel27.js +0 -225
  395. package/src/ardy/trim.js +0 -33
  396. package/src/ardy/waypoints.js +0 -369
  397. package/src/ardy-bridge-contract.js +0 -281
  398. package/src/domains/motion/motion-video-capture.js +0 -664
  399. package/src/i2v-motion-client.js +0 -77
  400. package/src/i2v-motion-studio.jsx +0 -180
  401. package/src/line-edit.js +0 -1348
  402. package/src/motion/generation.js +0 -105
  403. package/src/motion-readiness-ui.jsx +0 -67
  404. package/src/motion-readiness.js +0 -40
  405. package/src/motion-resources.js +0 -177
  406. package/src/motion-store.js +0 -65
  407. package/src/motion-trail.js +0 -601
  408. package/src/multimodel-ingest.js +0 -394
  409. package/src/panels/PromptBlocksPanel.jsx +0 -444
  410. package/src/panels/VideoCapturePanel.jsx +0 -181
  411. package/src/pose-extract/browser.js +0 -42
  412. package/src/pose-extract/detector.js +0 -100
  413. package/src/pose-extract/fit.js +0 -227
  414. package/src/pose-extract/image-frame.js +0 -51
  415. package/src/pose-extract/index.js +0 -58
  416. package/src/pose-extract/keyframes.js +0 -74
  417. package/src/pose-extract/landmarks.js +0 -162
  418. package/src/pose-extract/mirror.js +0 -153
  419. package/src/pose-extract/take.js +0 -131
  420. package/src/pose-extract/video-frames.js +0 -91
  421. package/src/take-recipe.js +0 -165
  422. package/src/trail-key-conflicts.js +0 -39
  423. package/src/trail-pick.js +0 -59
  424. package/src/use-i2v-capture-modal.js +0 -15
  425. package/tools/ardy/BRIDGE.md +0 -37
  426. package/tools/ardy/GVHMR-NPZ.md +0 -68
  427. package/tools/ardy/README.md +0 -124
  428. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  429. package/tools/ardy/artifacts.mjs +0 -34
  430. package/tools/ardy/bridge.mjs +0 -1732
  431. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  432. package/tools/ardy/cclay_constrained_generate.py +0 -561
  433. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  434. package/tools/ardy/cclay_motion_edit.py +0 -510
  435. package/tools/ardy/cclay_sequence_generate.py +0 -705
  436. package/tools/ardy/cclay_worker.py +0 -304
  437. package/tools/ardy/dump-npz.py +0 -205
  438. package/tools/ardy/extract-rest.mjs +0 -299
  439. package/tools/ardy/extract.mjs +0 -507
  440. package/tools/ardy/footage.mjs +0 -467
  441. package/tools/ardy/gvhmr-floor.mjs +0 -102
  442. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  443. package/tools/ardy/gvhmr_fastpath.py +0 -168
  444. package/tools/ardy/gvhmr_trajectory.py +0 -240
  445. package/tools/ardy/merge-text-encoder.py +0 -160
  446. package/tools/ardy/mocap-metrics.mjs +0 -200
  447. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  448. package/tools/ardy/motion-stabilize.mjs +0 -348
  449. package/tools/ardy/npz.mjs +0 -414
  450. package/tools/ardy/pose-to-npz.mjs +0 -106
  451. package/tools/ardy/prompt-limits.mjs +0 -5
  452. package/tools/ardy/run-edit-on-box.sh +0 -73
  453. package/tools/ardy/run-local.mjs +0 -233
  454. package/tools/ardy/run-on-box.sh +0 -593
  455. package/tools/ardy/run-sequence-on-box.sh +0 -177
  456. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  457. package/tools/ardy/runners/index.mjs +0 -18
  458. package/tools/ardy/runners/local.mjs +0 -455
  459. package/tools/ardy/runners/proc.mjs +0 -125
  460. package/tools/ardy/runners/remote.mjs +0 -252
  461. package/tools/ardy/setup-local.mjs +0 -189
  462. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  463. package/tools/ardy/setup-text-encoder.py +0 -306
  464. package/tools/ardy/smpl-cskel27.mjs +0 -178
  465. package/tools/ardy/visual-qa.mjs +0 -196
  466. package/tools/ardy/vq-car.mjs +0 -52
  467. package/tools/bench/EXP3.md +0 -61
  468. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  469. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  470. package/tools/bench/cclay_bench_runner.py +0 -42
  471. package/tools/bench/cube-contact.mjs +0 -162
  472. package/tools/bench/exp3.mjs +0 -152
  473. package/tools/bench/extract-bench-lib.mjs +0 -216
  474. package/tools/bench/extract-bench.mjs +0 -302
  475. package/tools/bench/fal-generate.mjs +0 -88
  476. package/tools/bench/fit/README.md +0 -189
  477. package/tools/bench/fit/camera.mjs +0 -59
  478. package/tools/bench/fit/contact.mjs +0 -419
  479. package/tools/bench/fit/footlock.mjs +0 -234
  480. package/tools/bench/fit/motion.mjs +0 -85
  481. package/tools/bench/fit/pin.mjs +0 -27
  482. package/tools/bench/fit/remote.mjs +0 -105
  483. package/tools/bench/fit-bench.mjs +0 -126
  484. package/tools/bench/fit-sanity.mjs +0 -45
  485. package/tools/bench/metrics.mjs +0 -313
  486. package/tools/bench/obs/depth.mjs +0 -258
  487. package/tools/bench/obs/extrinsics.mjs +0 -175
  488. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  489. package/tools/bench/obs/ground.mjs +0 -294
  490. package/tools/bench/obs/heading.mjs +0 -151
  491. package/tools/bench/obs/ladder.mjs +0 -555
  492. package/tools/bench/obs/mannequin-betas.json +0 -124
  493. package/tools/bench/obs/remote.mjs +0 -83
  494. package/tools/bench/obs/rest_joints.py +0 -52
  495. package/tools/bench/obs/ybot-targets.mjs +0 -49
  496. package/tools/bench/obs-bench.mjs +0 -520
  497. package/tools/bench/score.mjs +0 -343
  498. package/tools/bench/summarize.mjs +0 -86
  499. package/tools/demo-worker/README.md +0 -137
  500. package/tools/demo-worker/api-client.mjs +0 -233
  501. package/tools/demo-worker/generate.mjs +0 -301
  502. package/tools/demo-worker/index.mjs +0 -466
  503. package/tools/demo-worker/sign-core.mjs +0 -112
  504. package/tools/demo-worker/sign.mjs +0 -161
  505. package/tools/gt-render/browser.mjs +0 -182
  506. package/tools/gt-render/camera-math.mjs +0 -276
  507. package/tools/gt-render/page.mjs +0 -267
  508. package/tools/gt-render/render.mjs +0 -514
  509. package/tools/gt-render/scene-box.mjs +0 -31
  510. package/tools/gt-render/take-transform.mjs +0 -87
  511. package/tools/kimodo/compare-seam.mjs +0 -108
  512. package/tools/kimodo/constraints.mjs +0 -244
  513. package/tools/kimodo/edit.mjs +0 -259
  514. package/tools/kimodo/effector-constraints.mjs +0 -200
  515. package/tools/kimodo/generate.mjs +0 -646
  516. package/tools/kimodo/local-output.mjs +0 -265
  517. package/tools/kimodo/measure-pose.mjs +0 -65
  518. package/tools/kimodo/measure-preserve.mjs +0 -899
  519. package/tools/kimodo/measure-waypoints.mjs +0 -55
  520. package/tools/kimodo/mlx-generate.py +0 -111
  521. package/tools/kimodo/pose-constraints.mjs +0 -248
  522. package/tools/kimodo/preserve-mask.mjs +0 -543
  523. package/tools/kimodo/read-npz.mjs +0 -189
  524. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  525. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  526. package/tools/kimodo/runner.mjs +0 -284
  527. package/tools/kimodo/seam-batch.mjs +0 -77
  528. package/tools/kimodo/setup-local.mjs +0 -30
  529. package/tools/kimodo/setup-on-box.sh +0 -339
  530. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  531. package/tools/morphgs/assets/gen_truth.py +0 -39
  532. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  533. package/tools/morphgs/assets/playback-check.mjs +0 -30
  534. package/tools/morphgs/demo-gate.sh +0 -26
  535. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  536. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  537. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  538. package/tools/morphgs/setup-on-cluster.sh +0 -126
  539. package/tools/projflow/driver.py +0 -1069
  540. package/tools/projflow/generate.mjs +0 -805
  541. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  542. package/tools/projflow/line-edit-job.mjs +0 -547
  543. package/tools/projflow/replay.mjs +0 -452
  544. package/tools/projflow/runner.mjs +0 -269
  545. package/tools/projflow/service.mjs +0 -742
  546. package/tools/track/DESIGN.md +0 -513
  547. package/tools/track/backfill-provenance.mjs +0 -116
  548. package/tools/track/budget.mjs +0 -8
  549. package/tools/track/check-rig.mjs +0 -209
  550. package/tools/track/diagnostics.schema.json +0 -60
  551. package/tools/track/export-rig.mjs +0 -256
  552. package/tools/track/fallback.mjs +0 -7
  553. package/tools/track/fk-parity-fixture.mjs +0 -161
  554. package/tools/track/gate.mjs +0 -349
  555. package/tools/track/masks.mjs +0 -318
  556. package/tools/track/metrics.mjs +0 -201
  557. package/tools/track/publish-obs.mjs +0 -108
  558. package/tools/track/py/check_env.py +0 -61
  559. package/tools/track/py/eval_lr.py +0 -229
  560. package/tools/track/py/lr_viterbi.py +0 -294
  561. package/tools/track/py/masks.py +0 -405
  562. package/tools/track/py/objective.py +0 -382
  563. package/tools/track/py/rig.py +0 -508
  564. package/tools/track/py/scene.py +0 -326
  565. package/tools/track/py/test_joint_indices.py +0 -123
  566. package/tools/track/py/test_lr_viterbi.py +0 -195
  567. package/tools/track/py/test_masks.py +0 -229
  568. package/tools/track/py/test_rig.py +0 -288
  569. package/tools/track/py/test_scene.py +0 -354
  570. package/tools/track/py/test_track.py +0 -328
  571. package/tools/track/py/track.py +0 -411
  572. package/tools/track/remote.mjs +0 -140
  573. package/tools/track/rig-dump.mjs +0 -227
  574. package/tools/track/run-box-tests.mjs +0 -14
  575. package/tools/track/run-box.mjs +0 -168
  576. package/tools/track/setup-box.sh +0 -59
  577. package/tools/track/study-2d.mjs +0 -728
  578. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  579. /package/src/{ardy → motion}/ground.js +0 -0
  580. /package/src/{ardy → motion}/ik-drag.js +0 -0
  581. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  582. /package/src/{ardy → motion}/ik.js +0 -0
  583. /package/src/{ardy → motion}/physics-surface.js +0 -0
  584. /package/src/{ardy → motion}/playback-clock.js +0 -0
  585. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -0,0 +1 @@
1
+ {"model":"y-bot-tpose","units":"cm","mesh":"Alpha_Surface","bones":[{"name":"Hips","parent":-1,"localPos":[-0.000006757011760782916,99.79193878173828,0.00004844740033149719],"localQuat":[7.615435492247396e-11,-0.0000017453292503320135,0.00004363323128594654,0.9999999990465473],"worldPos":[-0.000006757011760782916,99.79193878173828,0.00004844740033149719],"worldQuat":[7.615435492247396e-11,-0.0000017453292503320135,0.00004363323128594654,0.9999999990465473]},{"name":"Spine","parent":0,"localPos":[0.0008597856133863019,9.923461876522225,-1.2273349078167588],"localQuat":[-0.06073022898235704,5.303745488019905e-22,0.000006119354919596912,0.9981542161661715],"worldPos":[-0.000008672608244745512,109.71540069587908,-1.227286457407732],"worldQuat":[-0.060730228859120175,-0.000004391963877518737,0.00004956605444176136,0.9981542149520963]},{"name":"Spine1","parent":1,"localPos":[0,11.731977989043784,-3.552713678800501e-15],"localQuat":[0.0001960924550491026,4.662287733052689e-14,-0.000009316072744031837,0.9999999807304797],"worldPos":[-0.0011632832276606084,121.36083978703566,-2.649627688070991],"worldQuat":[-0.06053449713743436,-0.00000494801144686156,0.00004026803743853935,0.9981661049195772]},{"name":"Spine2","parent":2,"localPos":[1.931491945550423e-11,13.458836780167971,6.235012506294879e-13],"localQuat":[0.057711730916465316,0.0000021958232674411106,0.000003285013706200134,0.9983332890868721],"worldPos":[-0.0022371547694859653,134.72103871836885,-4.27608729015328],"worldQuat":[-0.002827710078055566,-2.2517339024978275e-7,0.00004363254684471116,0.9999960010679366]},{"name":"Neck","parent":3,"localPos":[0.00002548122992670175,15.027761372130044,0.8779068542021755],"localQuat":[0.0028277058943183713,-8.816242878226746e-39,-7.234126583784003e-21,0.9999960020316957],"worldPos":[-0.003523660156014883,149.7535246254643,-3.4831824403326026],"worldQuat":[-4.186445695616128e-9,-1.017924801167934e-7,0.00004363300912729469,0.999999999048075]},{"name":"Head","parent":4,"localPos":[0.000002562548663041439,10.32183835340436,3.1424288991299827],"localQuat":[1.2407709188295404e-24,1.3234889800848435e-23,-3.3812794736012347e-21,1],"worldPos":[-0.0044224830930743595,160.07536296607333,-0.3407536277174854],"worldQuat":[-4.1864456956161264e-9,-1.0179248011679337e-7,0.000043633009127294685,0.999999999048075]},{"name":"HeadTop_End","parent":5,"localPos":[0.00015451594228192873,18.474670356296826,6.63639947863672],"localQuat":[6.93889473108785e-18,-6.61744490042423e-24,-1.0158249377722142e-20,1],"worldPos":[-0.005881529143937624,178.55003332101543,6.295645696100038],"worldQuat":[-4.186445688677232e-9,-1.0179248011679308e-7,0.00004363300912729468,0.999999999048075]},{"name":"LeftShoulder","parent":3,"localPos":[6.105824524896,9.10629188078309,0.757062475638635],"localQuat":[-0.45383506682997793,-0.5448493479758866,0.5511388470821386,-0.4397941465761588],"worldPos":[6.10279217248512,143.83199925791556,-3.5705353792059826],"worldQuat":[-0.4525659925709384,-0.5433084112379314,0.5526580275773418,-0.44109987213863294]},{"name":"LeftArm","parent":7,"localPos":[4.884981308350689e-15,12.92228632488431,2.842170943040401e-14],"localQuat":[-0.010451820107802023,-0.0010627185813176982,0.10115046260752789,0.9948156683526521],"worldPos":[18.75785325853472,143.5671732022338,-6.171454434247386],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftForeArm","parent":8,"localPos":[3.059411390893274e-9,27.404682159441652,-2.842170943040401e-14],"localQuat":[-1.0173904404505293e-20,6.815758221109549e-27,1.3234889800848457e-23,1],"worldPos":[46.162535310990236,143.5695947084291,-6.171442183765884],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftHand","parent":9,"localPos":[-0.000012820418092474029,27.614463806173113,2.3361064904747764e-7],"localQuat":[-3.397640826470449e-21,-1.8680226235633534e-27,5.2939559203393736e-23,1],"worldPos":[73.77699900937316,143.57203451753804,-6.171417016006557],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftHandRing1","parent":10,"localPos":[2.216630558205681,12.147010274148471,-0.009996226470974534],"localQuat":[5.56794949511021e-7,-3.067028835367668e-9,0.000004777353976607745,0.9999999999884335],"worldPos":[85.92400934395243,143.5831040665074,-8.388042142881478],"worldQuat":[0.49998068669282075,0.5000193094968617,-0.4999756886184537,0.500024313263825]},{"name":"LeftHandRing2","parent":11,"localPos":[0,3.601188659840844,0],"localQuat":[-0.000002306826384812874,1.861861504887997e-11,-0.000008071095064110734,0.999999999964768],"worldPos":[89.52519798990681,143.58341826103262,-8.388006124364832],"worldQuat":[0.4999754975118546,0.5000244982373176,-0.49997857087756026,0.5000214312542258]},{"name":"LeftHandRing3","parent":12,"localPos":[-7.140954494389007e-13,3.3073120118204997,2.2737367544323206e-13],"localQuat":[-3.2584970000852863e-21,-2.067951531382572e-25,-6.352747104407258e-22,1],"worldPos":[92.83250998771065,143.5837220743585,-8.388026432414401],"worldQuat":[0.49997549751185466,0.5000244982373176,-0.49997857087756026,0.5000214312542258]},{"name":"LeftHandRing4","parent":13,"localPos":[-0.0000241726316367874,3.660118102908669,0.000016886514032421474],"localQuat":[0.000008486035821629225,0.007396474405473809,0.0007707649842267434,0.9999723486255485],"worldPos":[96.49262807680708,143.5840414103271,-8.388024734185503],"worldQuat":[0.5040493957792119,0.5033194611486261,-0.4958855340273986,0.4966903097363882]},{"name":"LeftHandMiddle1","parent":10,"localPos":[-0.000018344155402694184,12.77552795411546,-0.0000010320898695681535],"localQuat":[5.567949752588633e-7,-2.6633364343577455e-9,2.0800236288001427e-7,0.9999999999998233],"worldPos":[86.55252691351437,143.5731644085546,-6.171392959489538],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle2","parent":15,"localPos":[-3.552713678800501e-15,3.61396789550858,-2.842170943040401e-14],"localQuat":[2.3697741078528623e-20,6.203854594147698e-25,-2.6469779601696844e-23,1],"worldPos":[90.16649479526663,143.5734797180353,-6.171389840137076],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle3","parent":16,"localPos":[0.000028508498060020315,3.4597625732240687,-8.526512829121202e-14],"localQuat":[1.692147750009982e-20,2.0679515313825724e-25,2.64697796016969e-23,1],"worldPos":[93.62625735534596,143.57378157349484,-6.171415362383127],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle4","parent":17,"localPos":[-0.000030473889779614183,3.680191040059995,-2.842170943040401e-14],"localQuat":[-0.00000133272714831852,0.004579424073341433,-0.000654144096597114,0.9999893004272004],"worldPos":[97.30644838137125,143.57410266077613,-6.171381711981186],"worldQuat":[0.5019349111684311,0.5026337814312043,-0.4980094305837711,0.4974004762403589]},{"name":"LeftHandThumb1","parent":10,"localPos":[-3.002975029424964,3.7888090485209744,2.1671489778191813],"localQuat":[0.25189492500135036,-0.05946403657250492,0.2219235197808198,0.940086659027326],"worldPos":[77.56599819190912,141.40522033116738,-3.168440292478436],"worldQuat":[0.6772116616355364,0.20343190021506413,-0.5147394802435296,0.484812432594653]},{"name":"LeftHandThumb2","parent":19,"localPos":[-1.9984014443252818e-15,4.744970523440218,2.842170943040401e-14],"localQuat":[0.0000069460704858849485,5.5796786860811154e-12,8.032883032279416e-7,0.9999999999755533],"worldPos":[81.24162844278966,139.28353174695044,-1.0464306132517085],"worldQuat":[0.6772151925776482,0.20342778079987783,-0.5147405038353289,0.48480814210593404]},{"name":"LeftHandThumb3","parent":20,"localPos":[-5.984102102729594e-13,4.3821287009303775,5.172751116333529e-12],"localQuat":[7.030691099565929e-18,7.121429504040547e-18,-1.5407439555097887e-32,1],"worldPos":[84.63615479208448,137.32403482337068,0.9133179986734019],"worldQuat":[0.6772151925776482,0.20342778079987775,-0.5147405038353289,0.48480814210593404]},{"name":"LeftHandThumb4","parent":21,"localPos":[-0.0000051284654249972306,3.459077859769903,4.03463474185628e-7],"localQuat":[0.009146816027813427,0.1256374250101491,0.07207247635857116,0.9894125182879566],"worldPos":[87.31565650284612,135.77728679427992,2.4602700847142343],"worldQuat":[0.7538118553684166,0.20866722684171796,-0.3911265183168664,0.4850213622280347]},{"name":"LeftHandIndex1","parent":10,"localPos":[-2.822044006965872,12.266617250897596,0.23182516767607808],"localQuat":[5.567949601161418e-7,-3.075281477739248e-9,0.00000487076476385117,0.9999999999879827],"worldPos":[86.04363543486608,143.34129324170544,-3.34936752423002],"worldQuat":[0.49998073339592125,0.5000192627891642,-0.4999756419148924,0.5000243599710406]},{"name":"LeftHandIndex2","parent":23,"localPos":[-1.3322676295501878e-15,3.891967773631521,0],"localQuat":[-3.0225470980600983e-21,0,-0.000006214320207710297,0.999999999980691],"worldPos":[89.93560319348254,143.34163280596658,-3.349327870283342],"worldQuat":[0.49997762610645813,0.5000223698198841,-0.4999787492167228,0.5000212529526508]},{"name":"LeftHandIndex3","parent":24,"localPos":[4.071321058063404e-11,3.415161132822689,-1.1368683772161603e-13],"localQuat":[4.6684518186119064e-23,-9.183549615799121e-41,2.1175823681357537e-22,1],"worldPos":[93.35076431329836,143.34193077006435,-3.3493355202090695],"worldQuat":[0.49997762610645813,0.5000223698198841,-0.4999787492167229,0.5000212529526508]},{"name":"LeftHandIndex4","parent":25,"localPos":[5.854722480158614e-7,3.0779876709090814,5.684341886080802e-14],"localQuat":[0.0000010393592226093013,0.004001602788212073,0.000022779581052790166,0.9999919932955144],"worldPos":[96.4287519724834,143.34219931663745,-3.3493430003052733],"worldQuat":[0.5019862492920715,0.5020073437901309,-0.4979631636001596,0.4980272281710877]},{"name":"LeftHandPinky1","parent":10,"localPos":[4.72583130478205,10.908194092064392,0.22613216873591568],"localQuat":[0.0000028521120612919424,-3.0577730863769185e-9,0.000141051374267014,0.9999999900481878],"worldPos":[84.68521515320175,143.3468662092345,-10.897243443373178],"worldQuat":[0.5000499694422342,0.49995002290857044,-0.49990869131728644,0.5000912946652625]},{"name":"LeftHandPinky2","parent":27,"localPos":[-5.329070518200751e-15,4.136657059551979,2.842170943040401e-14],"localQuat":[-0.0000059544873416476465,2.190560405006969e-9,-0.0003678839387923365,0.9999999323129735],"worldPos":[88.82187203349876,143.3472081321215,-10.896074631422186],"worldQuat":[0.4998630353195086,0.5001369272162459,-0.5000896549937187,0.49991032888321396]},{"name":"LeftHandPinky3","parent":28,"localPos":[4.3876013933186186e-13,2.594834461051775,0],"localQuat":[0.0000036591694282576963,8.409112616016821e-10,0.00022980932036022433,0.999999973587143],"worldPos":[91.41670621645012,143.34745351466333,-10.897250657097295],"worldQuat":[0.49997978792115133,0.5000202113293842,-0.49997658739741363,0.5000234114387793]},{"name":"LeftHandPinky4","parent":29,"localPos":[-2.948752353404416e-13,2.9238662720287607,-2.842170943040401e-14],"localQuat":[-0.0000010497831164166655,0.004099894588367042,-0.0005750644579927158,0.9999914300453439],"worldPos":[94.34057247729058,143.3477086145383,-10.89723194250163],"worldQuat":[0.5017372856540723,0.5023540149301887,-0.4982094589732469,0.49768210220741194]},{"name":"RightShoulder","parent":3,"localPos":[-6.1056956701096174,9.10638358733786,0.7570756312724551],"localQuat":[0.4538375688887134,-0.5448472538987562,0.5511399888422243,0.43979272809263187],"worldPos":[-6.1087279840345,143.8310253866605,-3.5705252284969617],"worldQuat":[0.45261579666489365,-0.5432669079313696,0.5526977464106563,0.44105012013225253]},{"name":"RightArm","parent":31,"localPos":[3.9968028886505635e-15,12.922286714484947,0],"localQuat":[-0.01045541384979725,0.0010630628959740092,-0.10114940861202837,0.9948157373885607],"worldPos":[-18.763745414580892,143.56389953844294,-6.171423447408117],"worldQuat":[0.5000215299672571,-0.4999784691060287,0.5000215360351153,0.4999784630368383]},{"name":"RightForeArm","parent":32,"localPos":[8.327427636345419e-9,27.404682159441318,-2.842170943040401e-14],"localQuat":[-3.388329060809388e-21,-1.5146129380243438e-28,8.271806125530284e-25,1],"worldPos":[-46.16842747236397,143.56153906740224,-6.171423771692651],"worldQuat":[0.5000215299672571,-0.49997846910602883,0.5000215360351153,0.4999784630368383]},{"name":"RightHand","parent":33,"localPos":[0.000012842842382454478,27.614463806155165,0.000015492399938921153],"localQuat":[-1.9727179218464944e-25,-7.573064690121704e-29,0,1],"worldPos":[-73.78289117474843,143.55914503465877,-6.17141126400836],"worldQuat":[0.5000215299672571,-0.4999784691060287,0.5000215360351153,0.4999784630368383]},{"name":"RightHandThumb1","parent":34,"localPos":[3.002974470681663,3.7888088905192205,2.1671490371761024],"localQuat":[0.25189499102226326,0.05946427874712486,-0.2219234615465524,0.9400866397658112],"worldPos":[-77.57151342274972,141.3916696607838,-3.168436839313407],"worldQuat":[0.6772291629398663,-0.20337279117491877,0.5147821060302558,0.4847675236487542]},{"name":"RightHandThumb2","parent":35,"localPos":[-6.8833827526759706e-15,4.744970470128291,2.842170943040401e-14],"localQuat":[0.000008453832451066965,-3.3376070678072775e-12,-3.9480215616198235e-7,0.9999999999641884],"worldPos":[-81.24677425676067,139.26933968812125,-1.0464288158806956],"worldQuat":[0.6772333413527709,-0.20336817191604672,0.5147836339017984,0.48476200168592604]},{"name":"RightHandThumb3","parent":36,"localPos":[-1.7763568394002505e-13,4.382135391768333,-4.092726157978177e-12],"localQuat":[-1.4347996972659013e-17,-5.998687332454958e-18,-1.387778780781447e-17,1],"worldPos":[-84.64095942776746,137.30923516924733,0.9133180789494266],"worldQuat":[0.6772333413527709,-0.20336817191604672,0.5147836339017984,0.48476200168592604]},{"name":"RightHandThumb4","parent":37,"localPos":[0.000011177533225659175,3.4590709023307085,-0.000023241859054223823],"localQuat":[0.00923206336161341,-0.1271302153500302,-0.0723276818427547,0.989202397788438],"worldPos":[-87.32019182850055,135.76203483248253,2.460268746809576],"worldQuat":[0.7545499013151971,-0.2090649481886763,0.389944180490974,0.4846543407061524]},{"name":"RightHandIndex1","parent":34,"localPos":[2.822042502024897,12.266617102415225,0.23182522345669554],"localQuat":[5.567922673046469e-7,-7.224337929733461e-9,-0.000004743924457641052,0.9999999999885925],"worldPos":[-86.04948829791044,143.32626324098368,-3.3493689108641775],"worldQuat":[0.5000241838181078,-0.4999758222398485,0.5000194389411731,0.4999805530753941]},{"name":"RightHandIndex2","parent":39,"localPos":[0,3.891967773619811,0],"localQuat":[1.695401251774016e-20,-4.135903062840235e-25,0.00000602627167052741,0.9999999999818419],"worldPos":[-89.94145605654246,143.32592367674323,-3.3493320316989923],"worldQuat":[0.5000211708188947,-0.4999788355123435,0.5000224519507367,0.4999775398133359]},{"name":"RightHandIndex3","parent":40,"localPos":[-5.1669779566054785e-12,3.4151611328221207,1.1368683772161603e-13],"localQuat":[-1.3593959205239575e-20,0,0,1],"worldPos":[-93.35661717635494,143.32562571266394,-3.349340831998884],"worldQuat":[0.5000211708188947,-0.4999788355123435,0.5000224519507367,0.4999775398133359]},{"name":"RightHandIndex4","parent":41,"localPos":[-0.0000012771572572845002,3.0779876709101757,-2.842170943040401e-14],"localQuat":[-0.00007290381402922513,-0.006709307422924062,0.0013745331778991744,0.9999765449936721],"worldPos":[-96.4346048355366,143.3253571661075,-3.3493500406116747],"worldQuat":[-0.5026405594004304,0.5040453607575476,-0.49730671352060296,-0.49596045712511533]},{"name":"RightHandMiddle1","parent":34,"localPos":[0.000016632154487439266,12.775527954114011,-0.0000010320893863990932],"localQuat":[5.567949633221699e-7,-7.289108692409176e-9,-3.662527039828292e-7,0.9999999999997777],"worldPos":[-86.55841908156046,143.55804566121927,-6.171394786911078],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle2","parent":43,"localPos":[8.881784197001252e-16,3.6139678955093757,0],"localQuat":[-3.3759614098155274e-21,-4.135903062765133e-25,0,1],"worldPos":[-90.17238696331393,143.55773035173834,-6.171392183522983],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle3","parent":44,"localPos":[-0.000029421479796454264,3.4597625732165085,1.4210854715202004e-13],"localQuat":[3.4003021678244415e-21,-8.271806125530284e-25,-7.940933880509075e-23,1],"worldPos":[-93.63214952338268,143.55742849627876,-6.1714191126993185],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle4","parent":45,"localPos":[0.000028549065814509333,3.680191040067001,-5.684341886080802e-14],"localQuat":[-0.00005158123071926063,-0.006695195594000001,-0.0017083442773867367,0.9999761263426065],"worldPos":[-97.31234054942114,143.557107408997,-6.171387912540353],"worldQuat":[0.504186145435319,-0.5024851098604104,0.49578202059538456,0.49749897806327625]},{"name":"RightHandRing1","parent":34,"localPos":[-2.216632303077052,12.147002761381543,-0.009996270293299858],"localQuat":[5.567954667309114e-7,-7.224304767843245e-9,-0.000004803651127566965,0.9999999999883074],"worldPos":[-85.92989472518438,143.5680950366908,-8.38804371451417],"worldQuat":[0.5000242136815972,-0.49997579237346873,0.5000194090805982,0.49998058293828956]},{"name":"RightHandRing2","parent":47,"localPos":[0,3.6011962892353893,-8.526512829121202e-14],"localQuat":[-5.732183384702703e-21,0,0.000008071083662125689,0.9999999999674287],"worldPos":[-89.53109100054763,143.5677808414962,-8.388009160440863],"worldQuat":[0.5000201783188615,-0.4999798280944457,0.5000234444494263,0.4999765472235214]},{"name":"RightHandRing3","parent":48,"localPos":[-6.055600465515454e-12,3.307312011785328,-1.1368683772161603e-13],"localQuat":[3.2821615918857455e-21,-3.6734198463196485e-40,2.1175823681357546e-22,1],"worldPos":[-92.83840299967426,143.56749228695628,-8.38803081342569],"worldQuat":[0.5000201783188615,-0.4999798280944457,0.5000234444494263,0.4999765472235214]},{"name":"RightHandRing4","parent":49,"localPos":[0.00002417262415121968,3.6601181029476635,-2.842170943040401e-14],"localQuat":[-0.00006164489635359998,-0.007613221748708619,-0.000300224892743606,0.9999709720384515],"worldPos":[-96.49852108877111,143.56717295098406,-8.388030603602541],"worldQuat":[0.5039317385023292,-0.503652452411389,0.49602123868179077,0.49633651979941534]},{"name":"RightHandPinky1","parent":34,"localPos":[-4.725833119502555,10.90819434071372,0.2261320753251539],"localQuat":[5.567949828639406e-7,-7.530380981813863e-9,-0.000003132050030138696,0.99999999999494],"worldPos":[-84.69106594001192,143.3320733953033,-10.897244515904388],"worldQuat":[0.5000233780731588,-0.4999766283665967,0.5000202446951756,0.49997974695226793]},{"name":"RightHandPinky2","parent":51,"localPos":[0,4.13665008553545,-2.842170943040401e-14],"localQuat":[1.470867824118891e-22,8.271806125977124e-25,0.000010394374390791114,0.9999999999459783],"worldPos":[-88.8277160097222,143.33171248313417,-10.897218653721097],"worldQuat":[0.5000181811018849,-0.4999818257697831,0.5000254416448413,0.49997454952763204]},{"name":"RightHandPinky3","parent":52,"localPos":[-3.950617610826157e-12,2.5948410036845218,-8.526512829121202e-14],"localQuat":[6.674018442413745e-21,1.836709923259698e-40,-0.000010428465638715964,0.9999999999456235],"worldPos":[-91.42255700325643,143.33148608987582,-10.897256374372848],"worldQuat":[0.5000233951179858,-0.49997661132017523,0.5000202276502416,0.4999797639985816]},{"name":"RightHandPinky4","parent":53,"localPos":[4.362732397567015e-12,2.923866272034857,5.684341886080802e-14],"localQuat":[-0.00008226663950025322,-0.00849884034311731,0.0022061069470672434,0.9999614472754239],"worldPos":[-94.34642326410449,143.33123099000105,-10.897237895108226],"worldQuat":[-0.5031095764062739,0.5053508241180749,-0.4968132089402998,-0.4946493041680384]},{"name":"LeftUpLeg","parent":0,"localPos":[9.123873709849553,-6.657188518716367,-0.05540310527662988],"localQuat":[0.000020251728747483253,-0.006350177975401161,0.9999754277247583,-0.002969642442257367],"worldPos":[9.12444806072654,93.13554649657034,-0.05532280954860631],"worldQuat":[0.000018783520922709306,-0.006350171978846871,0.999975297231096,-0.00301328568169704]},{"name":"LeftLeg","parent":55,"localPos":[-4.618527782440651e-14,40.59943638074365,1.170175067954915e-13],"localQuat":[-0.018114309191591866,0.00018249364298742092,-0.005920146666904975,0.9998183786878614],"worldPos":[9.369107731941927,52.540121711606496,-0.5709414745281038],"worldQuat":[-0.0000715314874584385,-0.02446331907456045,0.9996964939479204,0.00290876113461602]},{"name":"LeftFoot","parent":56,"localPos":[-1.0658141036401503e-14,42.09902591219656,2.0872192862952943e-14],"localQuat":[0.5405498192560871,0.01436647216366454,0.024951033886733327,0.8408192096329419],"worldPos":[9.12441738143423,10.49219684921195,-2.6300976499043784],"worldQuat":[-0.01346031169880001,0.5198601039256607,0.853859207560786,-0.022107600933591907]},{"name":"LeftToeBase","parent":57,"localPos":[1.7763568394002505e-15,15.721559146548017,-1.509903313490213e-14],"localQuat":[0.2276920621809942,-0.032521469150786096,-0.015365592016704316,0.9730686396375217],"worldPos":[9.497939603229476,3.2836504838127345,11.336461068911172],"worldQuat":[0.0016492651748272183,0.7007886739142866,0.7132730439227728,0.01157925951782756]},{"name":"LeftToe_End","parent":58,"localPos":[1.7763568394002505e-15,9.999999999999991,4.890746918562172e-9],"localQuat":[3.842630640765734e-10,-2.181956872127079e-18,8.673617379884037e-19,1],"worldPos":[9.355871856763304,3.108427383452366,21.333916426176543],"worldQuat":[0.0016492651792767014,0.700788674188371,0.7132730436534856,0.011579259517193808]},{"name":"RightUpLeg","parent":0,"localPos":[-9.125032356625555,-6.655601347887028,-0.05535274484958799],"localQuat":[-0.000017972283601838397,-0.006333801286546503,0.9999752669985558,0.0030574547301418053],"worldPos":[-9.12445807483328,93.1355411499169,-0.055336149820714026],"worldQuat":[-0.000019441205218510228,-0.006333807477113975,0.9999753994199062,0.00301381152055421]},{"name":"RightLeg","parent":60,"localPos":[7.105427357601002e-15,40.59943859177964,2.6645352591003757e-14],"localQuat":[-0.018147073530042527,-0.00018249394989624574,0.005920149654138874,0.9998177845219228],"worldPos":[-9.369160167563622,52.54009755727,-0.5696263108436963],"worldQuat":[0.00007086285029500266,-0.024479715368387448,0.9996960941175567,-0.0029082503401009767]},{"name":"RightFoot","parent":61,"localPos":[-2.4868995751603507e-14,42.09902387472938,-6.217248937900877e-14],"localQuat":[0.5405636018310247,-0.014366037304083883,-0.024951225824318232,0.8408103506008421],"worldPos":[-9.12451164224619,10.492242047309674,-2.6301615125796047],"worldQuat":[0.013459958226241265,0.5198600714589466,0.8538592128932476,0.02210837363015364]},{"name":"RightToeBase","parent":62,"localPos":[3.552713678800501e-15,15.721558809599616,2.6645352591003757e-15],"localQuat":[0.22770869920802236,0.03211960072148292,0.015257901862228916,0.9730797891155923],"worldPos":[-9.498060396707743,3.2836958492734345,11.33639620371245],"worldQuat":[-0.0013617607248561205,0.700801240791512,0.7132661380535977,-0.011277536030161229]},{"name":"RightToe_End","parent":63,"localPos":[3.1880595940947387e-9,9.999999999999998,5.687534443410414e-9],"localQuat":[-3.109963189751316e-10,-1.6439215440311446e-16,-1.7347234759768052e-18,1],"worldPos":[-9.356269180688868,3.1086870931784847,21.33385924122101],"worldQuat":[-0.0013617607213487338,0.7008012405696887,0.7132661382715444,-0.011277536030584614]}],"landmarks":{"mouth":[0,158.399150390625,12.493875312805176],"headEllipsoid":{"centre":[-0.000016689300537109375,167.32984161376953,0.6807799339294434],"radii":[8.005595684051514,13.133369445800781,12.374487400054932]},"headJoint":[-0.0044224830930743595,160.07536296607333,-0.3407536277174854],"headTop":[-0.005881529143937624,178.55003332101543,6.295645696100038],"sole":{"ball":3.3,"tip":2.6}}}
@@ -0,0 +1,60 @@
1
+ // Scene records -> what the motion compiler and QA collide with: each drawable object as an
2
+ // oriented box on its base pivot (bottom centre), sized by objectSize (scene-objects.js, the
3
+ // one owner of footprint x scale) and turned by the renderer's Euler XYZ (rotX, rot, rotZ).
4
+ // Every entry lists its `ancestors` (parent ids, nearest group first) and their poses
5
+ // (`ancestorPoses`, the same order), so a group (an Empty, which has no box of its own) is known
6
+ // by its parts (object-pose.js partsOf) and by its root pose. A saved take keeps scene.objects
7
+ // and scene.others (take-source.js), so the groups are rebuilt from the entries: groupsOf.
8
+ // `others` lists the records with no box (an Empty, a light, an effect, a plane) by id with their
9
+ // renderer and ancestors: a switch entry (C15) may name them, and a skill finds a kit's lit parts
10
+ // there. A body that glows (record.glow) says so (`glow: true`).
11
+ import { objectSize } from "../object-size.js";
12
+ import { mul, rx, ry, rz } from "./compiler/math.js";
13
+
14
+ const NO_BODY = new Set(["empty", "plane", "cutout"]);
15
+
16
+ /** Parent records of a record, nearest first (stops at a cycle, a missing parent or an attached record). */
17
+ function ancestorsOf(o, byId) {
18
+ const out = [];
19
+ for (let p = byId.get(o.parent); p && !out.includes(p) && !p.attach; p = byId.get(p.parent)) out.push(p);
20
+ return out;
21
+ }
22
+
23
+ const poseOf = o => ({ pos: [o.x ?? 0, o.y ?? 0, o.z ?? 0], R: mul(rx(o.rotX ?? 0), mul(ry(o.rot ?? 0), rz(o.rotZ ?? 0))) });
24
+
25
+ const groupCache = new WeakMap();
26
+
27
+ /**
28
+ * The groups of a motion scene, rebuilt from its body entries: { id: { pos, R, ancestors,
29
+ * children } }. A group is body-less; `children` lists its direct children (bodies and groups).
30
+ */
31
+ export function groupsOf(scene) {
32
+ const objects = scene?.objects ?? {};
33
+ if (groupCache.has(objects)) return groupCache.get(objects);
34
+ const groups = {};
35
+ for (const [id, o] of Object.entries(objects)) {
36
+ (o.ancestors ?? []).forEach((g, i) => {
37
+ const pose = o.ancestorPoses?.[i];
38
+ groups[g] ??= { pos: pose?.pos ?? [0, 0, 0], R: pose?.R ?? [[1, 0, 0], [0, 1, 0], [0, 0, 1]], ancestors: o.ancestors.slice(i + 1), children: [] };
39
+ const child = i ? o.ancestors[i - 1] : id;
40
+ if (!groups[g].children.includes(child)) groups[g].children.push(child);
41
+ });
42
+ }
43
+ groupCache.set(objects, groups);
44
+ return groups;
45
+ }
46
+
47
+ export function motionScene(objects = []) {
48
+ const out = {}, others = {}, byId = new Map(objects.filter(Boolean).map(o => [o.id, o]));
49
+ for (const o of objects) {
50
+ if (!o || o.hidden) continue;
51
+ const size = objectSize(o), up = ancestorsOf(o, byId);
52
+ if (NO_BODY.has(o.renderer) || !(size.width > 0 && size.height > 0 && size.depth > 0)) {
53
+ others[o.id] = { renderer: o.renderer, ancestors: up.map(p => p.id) };
54
+ continue;
55
+ }
56
+ out[o.id] = { name: o.name, renderer: o.renderer, ...poseOf(o), half: [size.width / 2, size.height / 2, size.depth / 2],
57
+ ancestors: up.map(p => p.id), ...(up.length ? { ancestorPoses: up.map(poseOf) } : {}), ...(o.glow ? { glow: true } : {}) };
58
+ }
59
+ return { objects: out, groups: groupsOf({ objects: out }), others };
60
+ }
@@ -0,0 +1,89 @@
1
+ // A JSON Schema fragment (describe.js) -> one short type line, for motion.describe
2
+ // { topic: "essentials" }: `{f: int, set: object, step?: string[]}`. `?` marks an optional
3
+ // field, `=v` a default, `lo..hi` a range, `A | B` a choice, `[key]: T` a map, `a_l|r` a field
4
+ // that has a twin with the same type, `a|b?: T` optional fields with the same schema; a $ref to a
5
+ // shared shape keeps its name (vec3, key, ...). With { means: true } each field also says what it
6
+ // means, `hand_l|r?: vec3 (the WRIST target in world metres)`, from the schema's description.
7
+
8
+ const BARE = { integer: "int", number: "number", string: "string", boolean: "bool" };
9
+ /** Descriptions that say only the unit: the essentials notes give the units once. */
10
+ const UNIT_ONLY = /^(degrees|m)$/;
11
+ const range = s => (s.minimum !== undefined && s.maximum !== undefined ? ` ${s.minimum}..${s.maximum}` : "");
12
+ /** A literal: strings in single quotes, so the JSON answer needs no escapes. */
13
+ const lit = v => (typeof v === "string" ? `'${v}'` : JSON.stringify(v));
14
+ const dflt = s => (s.default !== undefined ? `=${lit(s.default)}` : "");
15
+ const wrap = t => (/[ |]/.test(t) && !/^[{[].*[}\]]$/.test(t) ? `(${t})` : t);
16
+ /** The key name of a map from its description: "scene object or group id -> hinge or carry" -> "scene object or group id". */
17
+ const keyOf = s => s.description?.match(/^(?:[^:]*: )?(.+?) -> /)?.[1] ?? "name";
18
+
19
+ /** A value as a JS literal with single-quoted strings: an example inside a JSON string needs no escapes. */
20
+ export function literal(v) {
21
+ if (Array.isArray(v)) return `[${v.map(literal).join(", ")}]`;
22
+ if (v && typeof v === "object") return `{${Object.entries(v).map(([k, x]) => `${k}: ${literal(x)}`).join(", ")}}`;
23
+ return lit(v);
24
+ }
25
+
26
+ /** The tail a description shares with an earlier one in the same line, from a word after ", " or ": ". */
27
+ function sharedTail(d, earlier) {
28
+ let i = 0;
29
+ while (i < d.length && i < earlier.length && d[d.length - 1 - i] === earlier[earlier.length - 1 - i]) i += 1;
30
+ const tail = d.slice(d.length - i), cut = tail.search(/[,:] \S/);
31
+ return cut < 0 || tail.length - cut < 40 ? "" : tail.slice(cut + 2);
32
+ }
33
+
34
+ /** The fields of an object schema: `{ a: T, b?: T }`, a map `{ [key]: T }`, or both. */
35
+ function objectLine(s, opts) {
36
+ const req = new Set(s.required ?? []), props = Object.entries(s.properties ?? {});
37
+ if (opts.depth === 0) return "object";
38
+ const inner = { ...opts, depth: opts.depth === undefined ? undefined : opts.depth - 1, seen: undefined };
39
+ // a long table of optional numbers with defaults (checks.limits): the names only
40
+ if (props.length > 8 && !req.size && props.every(([, v]) => v.type === "number" && v.default !== undefined)) return `{ [${props.map(([k]) => k).join("|")}]: number }`;
41
+ const twinned = new Set(props.map(([, v]) => v.$ref?.match(/^#\/properties\/(.+)$/)?.[1]).filter(Boolean));
42
+ const said = [];
43
+ /** "(meaning)" once: a meaning that ends like an earlier field's says "as <that field>" instead of the tail;
44
+ * a field a sibling choice already explained (`opts.seen`, a switch's visible after a carry's) says nothing. */
45
+ const mean = (name, d) => {
46
+ if (opts.seen?.has(`${name}\0${d}`)) return "";
47
+ opts.seen?.add(`${name}\0${d}`);
48
+ for (const [n, e] of said) { const tail = sharedTail(d, e); if (tail) return ` (${d.slice(0, -tail.length - 2)}, as ${n})`; }
49
+ said.push([name, d]);
50
+ return ` (${d})`;
51
+ };
52
+ const typed = (name, v, t = briefType(v, inner)) => t + (opts.means && v.description && !UNIT_ONLY.test(v.description) && !t.includes(v.description) ? mean(name, v.description) : "");
53
+ // optional fields that read the same share one entry: `pitch|spine_pitch?: T`
54
+ const groups = new Map();
55
+ for (const [k, v] of props.filter(([, v]) => !v.$ref?.startsWith("#/properties/"))) {
56
+ const name = twinned.has(k) ? k.replace(/_l$/, "_l|r") : k, t = typed(name, v), same = req.has(k) ? `${k}\0` : t;
57
+ groups.set(same, { names: [...(groups.get(same)?.names ?? []), name], t, req: req.has(k) });
58
+ }
59
+ const fields = [...groups.values()].map(g => `${g.names.join("|")}${g.req ? "" : "?"}: ${g.t}`);
60
+ for (const [p, v] of Object.entries(s.patternProperties ?? {})) fields.push(`/${p}/: ${typed(p, v)}`);
61
+ const extra = s.additionalProperties && typeof s.additionalProperties === "object" ? s.additionalProperties : null;
62
+ if (extra) fields.push(`[${s.propertyNames?.enum?.join("|") ?? keyOf(s)}]: ${typed("", extra)}`);
63
+ return fields.length ? `{${fields.join(", ")}}` : `object${s.description ? ` (${s.description})` : ""}`;
64
+ }
65
+
66
+ /** schema -> type line; opts.means adds each field's meaning, opts.depth stops at that many object levels ("object"). */
67
+ export function briefType(s, opts = {}) {
68
+ if (!s || typeof s !== "object") return "any";
69
+ const title = s.title ? `${s.title} ` : "", brief = x => briefType(x, opts);
70
+ if (s.$ref) return s.$ref.split("/").pop() + dflt(s);
71
+ if ("const" in s) return lit(s.const);
72
+ if (s.enum) return s.enum.map(lit).join("|") + dflt(s);
73
+ if (s.oneOf) {
74
+ const shapes = s.oneOf.filter(o => !(Object.keys(o).length === 1 && o.required)), picks = s.oneOf.flatMap(o => (shapes.includes(o) ? [] : o.required));
75
+ const own = s.type === "object" || s.properties ? objectLine(s, opts) : "";
76
+ // the choices share what they explained: a field that reads the same in an earlier choice says nothing more
77
+ const seen = new Set(), choice = shapes.length && shapes.every(o => o.pattern && !o.type) ? `string: ${shapes.map(o => o.description ?? o.pattern).join("; ")}`
78
+ : shapes.map(x => briefType(x, { ...opts, seen })).join(" | ");
79
+ return [title + own, choice, picks.length ? `(one of ${picks.join("|")})` : ""].filter(Boolean).join(" ") + (own ? "" : dflt(s));
80
+ }
81
+ if (s.type === "array") {
82
+ if (!s.items && !s.prefixItems) return `array${s.description ? ` (${s.description})` : ""}`;
83
+ if (s.prefixItems) return `[${s.prefixItems.map(brief).join(", ")}]`;
84
+ const n = s.minItems === s.maxItems && s.maxItems ? ` (${s.maxItems})` : s.maxItems ? ` (<= ${s.maxItems})` : "";
85
+ return `${wrap(brief(s.items))}[]${n}`;
86
+ }
87
+ if (s.type === "object" || s.properties) return title + objectLine(s, opts);
88
+ return (BARE[s.type] ?? "any") + range(s) + dflt(s);
89
+ }
@@ -0,0 +1,44 @@
1
+ // C1. The motion spec's field tables, the one source the validator (compiler/validate*.js),
2
+ // the skills expander and motion.describe (describe.js) read. Channels, ranges and presets stay
3
+ // in compiler/vocab.js, FIX_KEYS in fix/index.js, QA_LIMITS in qa/checks.js and the skill names
4
+ // in skills/index.js; import those, never copy them here. See docs/motion-api-v3.1.md.
5
+
6
+ /** Top-level spec fields. */
7
+ export const SPEC_FIELDS = ["schema", "fps", "frames", "label", "keys", "anchors", "props", "fits", "objects", "generators", "checks", "fix", "use", "channels", "detourRadius", "search", "goals", "flow", "idle"];
8
+ /** One key: { f, set, step?, src? } (src is written by the skills expander). */
9
+ export const KEY_FIELDS = ["f", "set", "step", "src"];
10
+ /** One spec.use entry. */
11
+ export const USE_FIELDS = ["skill", "args", "f0"];
12
+ /** Anchor fields by anchor kind (besides `kind`). */
13
+ export const ANCHOR_FIELDS = { world: ["p"], body: ["p"], bone: ["bone", "offset"], segment: ["from", "to", "t", "tMin", "offset", "reach"],
14
+ object: ["object", "local"], landmark: ["name"], prop: ["prop", "point", "offset"], person: ["person", "bone", "offset"] };
15
+ export const PROP_FIELDS = ["hand", "origin", "points"];
16
+ export const FIT_FIELDS = ["side", "anchor", "effector", "offset", "orient"];
17
+ /** spec.objects[id]: a hinge or a carry (a body or a group id), see C3; carry keys: C14; a switch (any record, C15) moves nothing; a follow (any record, C16) rides a point of the body; a free entry (C17) moves by keys and falls. */
18
+ export const OBJECT_FIELDS = { hinge: ["pivot", "axis", "channel"], carry: ["prop", "at", "along", "visible", "level", "grab", "release", "keys", "fall"], switch: ["visible", "level"],
19
+ follow: ["follow", "offset", "aim", "visible", "level"], free: ["keys", "fall", "visible", "level"] };
20
+ /** One spec.objects[id].fall entry (C17): the frame it starts to fall, what it lands on, how much it bounces, whether it rolls to rest. */
21
+ export const FALL_FIELDS = ["at", "onto", "bounce", "tumble"];
22
+ /** One spec.objects[id].keys entry (C14): the held object's world pose at frame f; aim (+ roll) in place of rot (C16). */
23
+ export const OBJECT_KEY_FIELDS = ["f", "pos", "rot", "aim", "roll", "lean"];
24
+ export const WALK_FIELDS = ["type", "f0", "steps", "step", "period", "swing", "halfWidth", "lift", "heading", "turnDistance", "pelvisHigh", "pelvisLow", "firstStep", "armSwing", "vary"];
25
+ /** spec.checks keys. */
26
+ export const CHECK_FIELDS = ["contacts", "orient", "below", "clearance", "appear", "supports", "allow", "limits", "mouthPoints"];
27
+ /** Fields of one entry of each spec.checks list. */
28
+ export const CHECK_ENTRY_FIELDS = {
29
+ contacts: ["name", "point", "target", "tol", "when"],
30
+ orient: ["name", "from", "to", "along", "minCos", "when"],
31
+ below: ["name", "joint", "ref", "min", "when"],
32
+ clearance: ["name", "part", "object", "min", "frames"],
33
+ appear: ["name", "channel", "joint", "anchor", "tol"],
34
+ supports: ["object", "part", "tol"],
35
+ allow: ["part", "object", "depth"],
36
+ };
37
+ /** One spec.goals entry (C8): exactly one of near | above | moved | still | speed; after / before order it on another goal. */
38
+ export const GOAL_FIELDS = ["name", "near", "above", "moved", "still", "speed", "tol", "by", "at", "mode", "after", "before"];
39
+ /** One motion.compile probes entry (C5): exactly one of distance | position. */
40
+ export const PROBE_FIELDS = ["name", "distance", "position", "frames", "every"];
41
+ /** Point reference kinds (C2, refs.js). */
42
+ export const REF_KINDS = ["joint", "bone", "prop", "anchor", "landmark", "object", "person"];
43
+ /** motion.describe topics (C9); examples: whole specs that compile (schema/spec-examples.js). */
44
+ export const DESCRIBE_TOPICS = ["essentials", "spec", "skills", "anchors", "props", "objects", "checks", "goals", "probes", "channels", "refs", "fix", "examples"];
@@ -0,0 +1,46 @@
1
+ // motion.describe { topic: "examples" }: whole specs, each compiled at QA 0 on the scene its `scene`
2
+ // line names (test/bus/verify-motion3-examples.mjs builds those scenes and compiles every spec on
3
+ // both rigs). They come from the skills' and kits' own examples: reachGrip, smokeCigarette with
4
+ // args.kit and the squat of the smoke pacing test, the sword kit's props and carry, a hinge.
5
+ // Kept out of essentials (its budget is spent).
6
+ const SCHEMA = "cozyclay.motion-spec.v1";
7
+
8
+ export const SPEC_EXAMPLES = [
9
+ { name: "reachGrip carry: take a lantern off its hook and walk off with it",
10
+ scene: "lantern: a 14 x 20 x 14 cm box hanging at (0.3, 0.95, 0.4); the character at the origin, yaw 0",
11
+ spec: { schema: SCHEMA, fps: 24, frames: "auto", label: "take the lantern and walk off",
12
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } },
13
+ { skill: "reachGrip", f0: 10, args: { anchor: "handle", side: "l", define: { kind: "object", object: "lantern", local: [0, 0.22, 0] } } },
14
+ { skill: "walkTo", f0: 70, args: { to: [0, 1.6], steps: 4 } }],
15
+ objects: { lantern: { prop: "handleGrip", grab: 30 } },
16
+ goals: [{ name: "lantern carried off", moved: "object:lantern", by: 0.8, at: [170, 184] }] } },
17
+ { name: "squat and smoke, dressed by kits (smokeCigarette args.kit)",
18
+ scene: "object.createKit cigarette, lighter and exhale answered rootIds cig, lighter, exhale",
19
+ spec: { schema: SCHEMA, fps: 24, frames: 240, label: "squat and smoke",
20
+ keys: [{ f: 0, set: { root: [0, 0.45, -0.12], yaw: 0, pitch: 22, spine_pitch: 10, head_pitch: -12, foot_l: [0.16, 0.101, 0.02], foot_r: [-0.16, 0.101, 0.02],
21
+ fyaw_l: 15, fyaw_r: -15, knee_l: [0.45, 0, 1], knee_r: [-0.45, 0, 1] } }],
22
+ use: [{ skill: "smokeCigarette", f0: 1, args: { kit: { cig: "cig", lighter: "lighter", exhale: "exhale" } } }], fix: { retime: true },
23
+ goals: [{ name: "cigarette at the mouth", near: ["prop:cig.origin", "landmark:mouth"], tol: 0.08, at: [40, 230], mode: "any" }] } },
24
+ { name: "aim keys: raise a held sword to guard, then point it at a target",
25
+ scene: "object.createKit sword answered rootId sword and the props and bind below",
26
+ spec: { schema: SCHEMA, fps: 24, frames: 60, label: "sword to guard, then point",
27
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } }],
28
+ props: { swordGrip: { hand: "r", origin: ["RightHandIndex2", "RightHandMiddle2"], points: { tip: [0, 0.87, -0.015] } } },
29
+ anchors: { target: { kind: "world", p: [-0.25, 1.52, 1.13] } },
30
+ objects: { sword: { prop: "swordGrip", at: [0, 0, -0.015], along: [0, 1, 0], keys: [{ f: 20, pos: [-0.25, 1, 0.35], aim: [0, 0.7, 0.7] },
31
+ { f: 40, pos: [-0.25, 1.05, 0.4], aim: [0, 0.55, 0.85] }, { f: 59, pos: [-0.25, 1.05, 0.4], aim: [0, 0.55, 0.85] }] } },
32
+ goals: [{ name: "blade points at the target", near: ["prop:swordGrip.tip", "anchor:target"], tol: 0.1, at: [40, 59] }] } },
33
+ { name: "hinge: push a door open by its knob",
34
+ scene: "door: a 0.9 x 2 x 0.04 m box, base at (0, 0, 0.75), hinged on its +x edge",
35
+ spec: { schema: SCHEMA, fps: 24, frames: 72, label: "push the door open",
36
+ use: [{ skill: "standIdle", f0: 0, args: { at: [-0.1, 0.45], heading: 0 } },
37
+ { skill: "reachGrip", f0: 5, args: { anchor: "knob", side: "r", hold: 15, release: 8, define: { kind: "object", object: "door", local: [-0.35, 1, -0.04] } } }],
38
+ objects: { door: { pivot: [0.45, 0, 0.75], axis: [0, 1, 0], channel: "door" } },
39
+ keys: [{ f: 25, set: { door: 0 } }, { f: 40, set: { door: 10 } }, { f: 48, set: { door: 15 } }, { f: 70, set: { door: 75 } }],
40
+ goals: [{ name: "door swung open", moved: "object:door", by: 0.3, at: [60, 71] }] } },
41
+ ];
42
+
43
+ export const EXAMPLE_NOTES = [
44
+ "Each spec compiles at QA 0 on its scene. Ids are examples: use the scene's (object.createKit answers rootId, props and bind).",
45
+ "The lantern rides the hand from grab on (no release); the knob anchor follows the hinged door; aim keys pose the sword, the arm follows; the last key holds the pose.",
46
+ ];
@@ -0,0 +1,113 @@
1
+ // motion.describe examples and notes, one per topic (describe.js builds the schemas from
2
+ // fields.js and types.js). Each example is a part of a spec that passes validation when merged
3
+ // into a spec with standIdle at f0 0 and frames 60 (probes: a motion.compile probes list);
4
+ // test/motion3/verify-motion3-describe.mjs checks that. Object ids are examples: use the scene's.
5
+ import { CONVENTIONS } from "../compiler/vocab.js";
6
+ import { FIX_KEYS } from "../fix/index.js";
7
+ import { literal } from "./brief.js";
8
+ import { WRIST_LIMITS } from "../compiler/arm-orient.js";
9
+ import { KEY_BLEND } from "../object-keys.js";
10
+
11
+ const SPOT = { kind: "world", p: [-0.2, 1.1, 0.35] };
12
+ const GRIP = { hand: "r", origin: ["RightHandIndex2", "RightHandMiddle2"], points: { fingers: [0, 0, 0] } };
13
+
14
+ export const EXAMPLES = {
15
+ spec: { schema: "cozyclay.motion-spec.v1", fps: 24, frames: "auto", label: "walk up and grip the bar",
16
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } }, { skill: "walkTo", f0: 10, args: { to: [0, 1.2] } },
17
+ { skill: "reachGrip", f0: 140, args: { anchor: "bar", side: "r", define: { kind: "world", p: [-0.2, 1.2, 1.6] } } }],
18
+ keys: [{ f: 150, set: { head_pitch: 10 } }] },
19
+ anchors: { anchors: { spot: SPOT, pocket: { kind: "body", p: [0.13, -0.035, 0.08] }, knee: { kind: "segment", from: "LeftUpLeg", to: "LeftLeg", t: 0.45, reach: "l" },
20
+ handle: { kind: "object", object: "cup", local: [0.07, 0, 0] }, mouth: { kind: "landmark", name: "mouth" } },
21
+ keys: [{ f: 10, set: { armw_r: 1, w_spot_r: 0 } }, { f: 30, set: { w_spot_r: 1 } }] },
22
+ props: { props: { cupGrip: GRIP }, anchors: { spot: SPOT }, fits: [{ side: "r", anchor: "spot", effector: { prop: "cupGrip", point: "fingers" } }] },
23
+ objects: { props: { cupGrip: GRIP },
24
+ objects: { cup: { prop: "cupGrip", grab: 20, release: 50 }, door: { pivot: [0.9, 0, 0.5], axis: [0, 1, 0], channel: "door" },
25
+ bat: { prop: "cupGrip", grab: 52, keys: [{ f: 54, pos: [0.3, 1.2, 0.2], rot: [0, 0, 0.38268, 0.92388] }, { f: 58, pos: [0.3, 1.1, 0.4], aim: [0, -0.2, 1] }] },
26
+ ember: { visible: "ember_vis", level: "ember" }, puff: { follow: "landmark:mouth", aim: "face", visible: "ember_vis" } },
27
+ keys: [{ f: 0, set: { door: 0, ember_vis: 0, ember: 0.6 } }, { f: 30, set: { ember_vis: 1, ember: 2 }, step: ["ember_vis"] }, { f: 40, set: { door: -60 } }] },
28
+ checks: { anchors: { spot: SPOT }, checks: {
29
+ contacts: [{ name: "right hand on the spot", point: "joint:RightHand", target: "anchor:spot", tol: 0.05, when: [30, 40] }],
30
+ clearance: [{ name: "hand off the cup", part: "hand_r", object: "cup", min: 0.01, frames: [0, 20] }],
31
+ allow: [{ part: "hand", object: "cup", depth: 0.03 }], limits: { object: 0.01 } } },
32
+ goals: { anchors: { spot: SPOT }, goals: [
33
+ { name: "hand at the spot", near: ["joint:RightHand", "anchor:spot"], tol: 0.06, at: [30, 40] },
34
+ { name: "hand over the table", above: ["joint:RightHand", "object:table.top"], by: 0.05, at: 35, mode: "any" },
35
+ { name: "cup lifted", moved: "object:cup", by: 0.1, at: [40, 59], after: "hand at the spot" },
36
+ { name: "cup still before", still: "object:cup", at: [0, 59], before: "cup lifted" },
37
+ { name: "hand quick", speed: "joint:RightHand", by: 1.2, at: [20, 30] }] },
38
+ probes: [{ name: "handToCup", distance: ["joint:RightHand", "object:cup"], frames: [0, 59] }, { name: "cupTop", position: "object:cup.top", frames: [0, 59], every: 10 }],
39
+ channels: { anchors: { spot: SPOT }, channels: ["lid"], keys: [
40
+ { f: 0, set: { armw_r: 1, hand_r: [-0.25, 1.0, 0.2], elbow_r: [-0.5, -1, -0.3], fingers_r: { grip: 0 }, lid: 0 } },
41
+ { f: 20, set: { w_spot_r: 1, fingers_r: { grip: 1 }, head_yaw: -15, spine_pitch: 8 } },
42
+ { f: 30, set: { lid: 1 }, step: ["lid"] }] },
43
+ refs: { props: { cupGrip: GRIP }, anchors: { spot: SPOT }, goals: [
44
+ { name: "fingers at the spot", near: ["prop:cupGrip.fingers", "anchor:spot"], at: 30 },
45
+ { name: "cup at the mouth", near: ["object:cup.top", "landmark:mouth"], tol: 0.06, at: [40, 50] },
46
+ { name: "hand above the hips", above: ["joint:RightHand", "bone:Hips"], at: 30 }] },
47
+ fix: { fix: { reach: true, slide: true, penetration: 0.02, self: true, retime: false } },
48
+ };
49
+
50
+ const UNITS = `World metres, +Y up; ${CONVENTIONS.yaw}; the character's left is +X at yaw 0. Angles in degrees.`;
51
+ const NO_JUMP = "Without at/along it keeps its grab-frame offset to the palm: no jump.";
52
+ /** The objects example's carry: a grip prop and the object it holds. */
53
+ const CARRY = { props: EXAMPLES.objects.props, objects: { cup: EXAMPLES.objects.objects.cup } };
54
+
55
+ export const NOTES = {
56
+ essentials: ["types: ? optional, =v default, a..b range, A | B one of, [key]: T map, a|b?: T both, x_l|r each side, (text) meaning.",
57
+ `A carried object: ${literal(CARRY)}. ${NO_JUMP}`,
58
+ "motion.describe { topic } or { topic: 'skills', name }: the rest."],
59
+ spec: [UNITS,
60
+ "frames: an integer, or \"auto\" (the last skill end, generator end or key f, plus 1); the stored spec keeps the number.",
61
+ "Any number may be { range: [lo, hi] } (int: true for frames): the compiler searches it, QA 0 first, at most search.budget compiles.",
62
+ "use expands skills (topic skills) into keys, anchors, props, fits and checks first; your own keys win on the same frame and your anchors/props replace a skill's.",
63
+ "Keys ease between values (step jumps); a channel holds its last value. Unknown fields are refused with the field list.",
64
+ "More: topics anchors, props, objects, checks, goals, probes, channels, refs, fix, skills."],
65
+ anchors: ["An anchor is a named point a hand can go to: key w_<anchor>_l / w_<anchor>_r from 0 to 1 with armw_<side> 1 (the IK arm).",
66
+ "An anchor name may not end in _l or _r.", "object anchors (a body or a group; local in its own axes) follow the object where it is (hinges, carries): put the other hand on a carried object with one; the carrying hand's own anchor stays where it took it. prop anchors are a point of a prop the other hand holds.",
67
+ "segment with reach slides from t toward tMin until the arm reaches it.",
68
+ "person { person: <character id>, bone, offset? } is another character's joint where its installed take has it that frame (a hand on a shoulder, a push on the chest): install that character's take first; reachGrip on it allows the hand to touch that person."],
69
+ props: ["A prop is a set of points fixed to one hand, [d, l, n] along the palm axes; prop:<prop>.origin is the mean of its origin bones.",
70
+ "fits: the hand target moves so the effector (a prop point or the mean of joints), not the wrist, lands on the anchor.",
71
+ "A fit on a scene body also turns the hand about the forearm into a grip: a thin body (a can, a bar, a handle, a neck) across the palm, else thumb up; never past a comfortable forearm turn. A wrist you turn (wtwist/wflex) wins; fit.orient: false (reachGrip args.orient: false) turns it off.",
72
+ "reachGrip adds props.<anchor>Grip and its fit. Carry a scene object with objects.<id>.prop (topic objects)."],
73
+ objects: ["A hinge turns the object (a body or a group) about pivot/axis by the angle channel your keys set (degrees).",
74
+ "A carry follows the prop's hand: before grab the scene pose, grab..release in the hand, after release frozen where it was let go.",
75
+ `No grab: in hand from frame 0; no release: to the end. ${NO_JUMP}`,
76
+ "A group (Empty) id moves all its parts; at/along pin a group's root to the palm too (an object.createKit kit). A carried object is an obstacle for the body and the scene.",
77
+ "A switch { visible?, level? } (no prop, no hinge field) moves nothing: it shows or hides any record (a part, a light, an effect) and sets its level, 0..4 light, glow and effect strength "
78
+ + "(an unkeyed level reads 1). Hiding a group hides its parts. A carry takes level too.",
79
+ "keys pose a carried object in the world while it is in hand (grab <= f <= release): pos is its base (a group: its root), rot a quaternion [x, y, z, w], "
80
+ + "or aim [x, y, z] the direction its +Y points (a bat's barrel), turned from how the hand holds it there, plus roll degrees about aim; no roll: the roll the arm holds most easily. "
81
+ + `The object leads and the whole arm follows (the elbow swings, the forearm turns, the wrist adds the rest within ${Object.entries(WRIST_LIMITS).map(([k, [lo, hi]]) => `${k} ${lo}..${hi}`).join(", ")} deg; dev + toward the thumb); `
82
+ + "a left hand on a prop anchor of it turns with it; "
83
+ + `the hand eases in and out over ${KEY_BLEND} frames. A REACH group "<id>: n cm off its keys" is what the hand could not reach; `
84
+ + "output.observations.held measures every key as drawn (deg off the asked +Y, cm off pos, the drawn +Y, the rot an aim key used).",
85
+ "free { keys?, fall? } moves what nobody holds: keys at any frame; fall drops it at frame at onto the still top below (onto: that one; else the floor) "
86
+ + "to rest on a stable face, one small bounce (0: none). A carry falls before grab or after release.",
87
+ "A follow { follow: <ref>, offset?, aim?, visible?, level? } puts any record (an effect, a light, a part) on a body point every frame: "
88
+ + "aim sets its +Y (an effect emits along it): up (default), face (forward), a direction or a ref (toward it); offset is metres along its axes after aim. It is no obstacle.",
89
+ "The editor's motion.keyObject writes one key from a drag (a hinge: its channel key)."],
90
+ checks: ["Each entry adds QA groups: contacts CONTACT, orient ORIENT, below BELOW, clearance CLEARANCE, appear APPEAR; supports mark where a part rests on an object (no FLOAT, no balance there); a foot on an object's top is on the ground without one.",
91
+ "when: a weight channel (active above 0.99) or [f0, f1]; clearance uses frames.", "Check points take joint:, prop: and anchor: only; goals and probes take every ref (topic refs).",
92
+ "allow excuses a body part inside an object up to depth; limits override the QA limits. Unnamed entries are named by place, contacts[0].",
93
+ "Other characters with an installed take are bodies too: PERSON \"<part> x person:<id>\" is a part inside that person; a touch you mean (a push, a hug) is allow { part, object: \"person:<id>\", depth }.",
94
+ "Speed, acceleration, knee bend and balance are style: measured in output.observations, not judged. Naming speedCore/speedLimb, accCore/accLimb, knee or balance in limits makes it a check (SPEED, ACC, KNEE, BALANCE). observations.near: each hand's and foot's nearest object and gap (< 0 inside), measured, not judged.",
95
+ "motion.qa { checks } replaces every check for a re-measure."],
96
+ goals: ["Exactly one of near (distance <= tol), above (a.y - b.y >= by), moved (an object's base moved at least by from the scene pose; any other point ref, e.g. prop:bat.tip, at least by from where it is at at[0], at: [f0, f1]), still (stays within tol, default 0.01 m, of where moved measures from) or speed (the point reaches by m/s).",
97
+ "at is an absolute frame or [f0, f1]; mode all (every frame; the default) or any (one frame; speed's default). A failed goal is a GOAL group first in qa.groups and makes qa.ok false.",
98
+ "after / before: another goal's name; at is cut to the frames after (before) the first frame that goal holds, so cause and effect keep their order wherever the event lands (the can moves after the kick). If that goal never holds, this one fails with value null.",
99
+ "Intent lines as goals: a contact is near between the touching point (joint:RightHandIndex4, joint:RightToeBase) and the object, tol 0.02-0.03; a negative is still on the object before: \"<contact goal>\"; an effect is moved on the object after: \"<contact goal>\" (mode any); a strike is speed of the joint, by m/s, before: \"<contact goal>\"; an effect on something nobody holds (a can that drops, a machine that rocks) moves it by spec.objects keys or fall (topic: \"objects\"), not a hinge or a swapped copy.",
100
+ "A cup or can brought to the mouth: give its aim keys lean 20-30 so the elbow stays low (observations.wrist raised counts the frames with the elbow over the shoulder)."],
101
+ probes: ["motion.compile { probes } (at most 16); spec.probes are measured too, not stored; answered whether or not it installs.",
102
+ "distance [a, b] -> { min, minAt, max, maxAt, mean, first, last } in m; a bare object:<id> measures to its surface. position -> { at: [{ f, p }] }, at most 16 rows."],
103
+ channels: ["key.set names channels; values ease between keys and hold after the last key. step: [channel] jumps at f instead.",
104
+ "Flow (spec.flow, on by default): the spine, head, arm swing/bend and wrist carry their speed through a key (a small overshoot) and trail the body (spine 1, head 2, arms 3 frames; lag: { spine, head, arms } or a number); feet, root, hand targets, weights, poles, fingers and objects land on their keys on time. flow: false turns it off; { smooth: false } or { lag: false } one part.",
105
+ "w_<anchor>_<side> (0..1) weights a hand onto an anchor; the weights of one hand add up to at most 1.",
106
+ "Any other numeric channel must come from spec.channels, a hinge (objects.<id>.channel), a check's when or a visible switch; names ending _vis are visibility switches (shown above 0.5)."],
107
+ refs: ["A ref names a point: joint:/bone:<Bone>, prop:<prop>.<point>, anchor:<name>, landmark:mouth, object:<id>[.center|.top|.base], person:<character id>.<Bone> (another character's joint in its installed take).",
108
+ "object:<id> takes a body or a group (the box around its parts); in a distance a bare object:<id> means its surface.",
109
+ "Goals and probes take every kind; spec.checks keep joint:, prop: and anchor:."],
110
+ fix: [`spec.fix keys: ${FIX_KEYS.join(", ")}; false turns all off. output.fixed reports what each one changed.`,
111
+ "reach, slide and self are on by default; penetration and retime are opt-in.",
112
+ "self keeps the arms out of the body on its fitted skin (QA BODY measures the same skin): wrist targets inside it go onto it, elbows turn about the shoulder-wrist line, a hand a little inside is pushed out. A fit's target (the mouth) is never moved; what is left is BODY, with checks.allow { part, object: <body part>, depth } for a contact meant to touch (a hand on a knee)."],
113
+ };
@@ -0,0 +1,149 @@
1
+ // JSON Schema 2020-12 fragments for the fields of each table in schema/fields.js, keyed by the
2
+ // field name. The field lists themselves stay in fields.js: describe.js walks those lists and
3
+ // looks each field up here, and throws when one is missing, so a new field needs a type here.
4
+ // Shared shapes are $refs into DEFS (describe.js adds the ones an answer uses).
5
+ import { REF_KINDS, OBJECT_KEY_FIELDS } from "./fields.js";
6
+ import { CONVENTIONS } from "../compiler/vocab.js";
7
+ import { QA_LIMITS } from "../qa/checks.js";
8
+ import { CAPSULES } from "../qa/geometry.js";
9
+
10
+ const def = (d, extra) => ({ ...extra, ...(d ? { description: d } : {}) });
11
+ export const num = (d, extra) => def(d, { type: "number", ...extra });
12
+ export const int = (d, extra) => def(d, { type: "integer", ...extra });
13
+ export const str = (d, extra) => def(d, { type: "string", ...extra });
14
+ const bool = (d, extra) => def(d, { type: "boolean", ...extra });
15
+ export const ref = (name, d) => def(d, { $ref: `#/$defs/${name}` });
16
+ export const side = d => def(d, { enum: ["l", "r"] });
17
+ const pair = (items, d) => def(d, { type: "array", prefixItems: [items, items], minItems: 2, maxItems: 2 });
18
+
19
+ export const DEFS = {
20
+ vec3: { type: "array", items: { type: "number" }, minItems: 3, maxItems: 3 },
21
+ frameSpan: { type: "array", items: { type: "integer", minimum: 0 }, minItems: 2, maxItems: 2, description: "[f0, f1] inclusive" },
22
+ ref: { type: "string", pattern: `^(${REF_KINDS.join("|")}):.+$`, description: "a point ref (topic refs)" },
23
+ checkRef: { type: "string", pattern: "^(joint|prop|anchor):.+$", description: "joint:<Bone> | prop:<prop>.<point> | anchor:<name>" },
24
+ part: { type: "string", description: `a body capsule: ${CAPSULES.map(c => c[0]).join(", ")}; allow matches a prefix (hand = hand_l and hand_r)` },
25
+ when: { oneOf: [{ type: "string", description: "a weight channel: active where it is > 0.99" }, { $ref: "#/$defs/frameSpan" }] },
26
+ };
27
+
28
+ export const KEY_TYPES = {
29
+ f: int("frame", { minimum: 0 }), set: { type: "object", description: "{ channel: value } (topic channels)" },
30
+ step: { type: "array", items: { type: "string" }, description: "channels that jump at f instead of easing in" },
31
+ src: str("written by the skills expander; leave it out"),
32
+ };
33
+
34
+ export const USE_TYPES = { skill: str("a skill name (topic skills)"), args: { type: "object", description: "the skill's args (topic skills with name)" }, f0: int("first frame", { minimum: 0 }) };
35
+
36
+ export const WALK_TYPES = {
37
+ type: { const: "walk" }, f0: int("first frame; needs a standing pose keyed before it", { minimum: 0 }), steps: int("footsteps", { minimum: 1, default: 8 }),
38
+ step: num("stride, m", { default: 0.5 }), period: int("frames per step", { default: 20 }), swing: int("frames a foot is in the air", { default: 14 }),
39
+ halfWidth: num("feet half-width, m", { default: 0.08 }), lift: num("foot lift, m", { default: 0.08 }), heading: pair({ type: "number" }, `[h0, h1] degrees; ${CONVENTIONS.yaw}`),
40
+ turnDistance: num("m walked while the heading turns h0 -> h1", { default: 0.4 }), pelvisHigh: num("hips offset over the stance foot, m"),
41
+ pelvisLow: num("hips offset at double support, m"), firstStep: num("first stride, m", { default: 0.4 }), armSwing: num("degrees", { default: 14 }),
42
+ vary: num("0..2, uneven steps as people walk (build-up, slow stop, left/right, turns) around the averages above; 0 = every step period frames, step m", { default: 1, minimum: 0, maximum: 2 }),
43
+ };
44
+
45
+ export const SPEC_TYPES = {
46
+ schema: { const: "cozyclay.motion-spec.v1" }, fps: { const: 24 },
47
+ frames: { oneOf: [int(null, { minimum: 1, maximum: 20000 }), { const: "auto", description: "the last skill end, generator end or key f, plus 1 (open values at their upper bound); the stored spec keeps the number" }] },
48
+ label: str("a short name for the take"),
49
+ keys: { type: "array", items: { $ref: "#/$defs/key" } },
50
+ anchors: { type: "object", description: "name -> anchor (topic anchors)" }, props: { type: "object", description: "name -> held prop (topic props)" },
51
+ fits: { type: "array", description: "topic props" }, objects: { type: "object", description: "scene object id -> hinge, carry, switch, follow or free (topic objects)" },
52
+ generators: { type: "array", items: { $ref: "#/$defs/walk" } }, checks: { type: "object", description: "topic checks" },
53
+ fix: { oneOf: [{ const: false }, { type: "object" }], description: "topic fix" }, use: { type: "array", items: { $ref: "#/$defs/use" } },
54
+ channels: { type: "array", items: { type: "string" }, description: "extra numeric channels your keys set" },
55
+ detourRadius: num("m; a hand moving between targets arcs around the torso this far out", { default: 0.25 }),
56
+ search: { type: "object", properties: { budget: int("compiles at most", { minimum: 1, maximum: 64, default: 32 }) }, additionalProperties: false },
57
+ goals: { type: "array", description: "topic goals" },
58
+ flow: { oneOf: [{ const: false }, { type: "object" }] },
59
+ idle: { const: false, description: "held poses do not breathe" },
60
+ };
61
+
62
+ export const ANCHOR_TYPES = {
63
+ p: ref("vec3", `world: a world point (m); body: root-relative, ${CONVENTIONS.pole}`), bone: str("bone name"), offset: ref("vec3", "world offset, m"),
64
+ from: str("bone"), to: str("bone"), t: num("0 = from .. 1 = to", { default: 0.5 }), tMin: num("with reach: the lowest t to slide back to", { default: 0.15 }),
65
+ reach: side("slide toward `from` until this arm reaches"), object: str("scene object id"), local: ref("vec3", "point in the object's frame, m"),
66
+ name: { const: "mouth" }, prop: str("a prop held by the other hand"), point: str("a point of that prop, or origin"),
67
+ person: str("a character id"),
68
+ };
69
+
70
+ const palm = d => ref("vec3", `${d} [d, l, n] on the palm axes (d to the middle finger, l to the thumb side, n = d x l), m`);
71
+ /** Fields an anchor of each kind must have. */
72
+ export const ANCHOR_REQUIRED = { world: ["p"], body: ["p"], bone: ["bone"], segment: ["from", "to"], object: ["object"], landmark: ["name"], prop: ["prop", "point"], person: ["person", "bone"] };
73
+
74
+ export const PROP_TYPES = {
75
+ hand: side(), origin: { type: "array", items: { type: "string" }, minItems: 1, description: "bones whose mean is the prop origin" },
76
+ points: { type: "object", additionalProperties: palm("point:"), description: "name -> point" },
77
+ };
78
+
79
+ export const FIT_TYPES = {
80
+ side: side(), anchor: str("an anchor name"),
81
+ effector: { oneOf: [{ type: "object", properties: { prop: str(), point: str() }, required: ["prop", "point"] }, { type: "object", properties: { joints: { type: "array", items: { type: "string" } } }, required: ["joints"] }],
82
+ description: "the hand point fitted onto the anchor" },
83
+ offset: ref("vec3", "world offset, m"), orient: { type: "boolean", description: "false: no grip turn" },
84
+ };
85
+
86
+ const OBJECT_KEY_TYPES = { f: int(), pos: ref("vec3"), rot: { type: "array", items: { type: "number" }, minItems: 4, maxItems: 4, description: "quat x, y, z, w" },
87
+ aim: ref("vec3", "or rot: +Y dir"), roll: num("deg about aim"), lean: num("aim tilt", { minimum: 0, maximum: 45 }) };
88
+
89
+ const FALL = { type: "object", properties: { at: int(), onto: str(), bounce: num(null, { default: 0.25, minimum: 0, maximum: 0.6 }), tumble: { type: "boolean" } }, required: ["at"], additionalProperties: false };
90
+ /** A free entry's keys and fall (C17) are a carry's, at any frame: said once, not twice. */
91
+ const AS_CARRY = { description: "as carry; keys at any frame" };
92
+ export const FREE_TYPES = { keys: AS_CARRY, fall: AS_CARRY };
93
+
94
+ export const OBJECT_TYPES = {
95
+ pivot: ref("vec3", "world hinge point"), axis: ref("vec3", "default +Y"), channel: str("angle channel, deg"),
96
+ prop: str("spec.props name: it rides that hand"), at: ref("vec3", "palm offset [d, l, n]"), along: ref("vec3", "+Y on the palm, fixed"),
97
+ visible: str("channel: shown > 0.5"), level: str("channel: strength 0..4"), grab: int("hand takes it", { default: 0 }), release: int("let go (else end)"),
98
+ keys: { type: "array", items: { type: "object", properties: Object.fromEntries(OBJECT_KEY_FIELDS.map(f => [f, OBJECT_KEY_TYPES[f]])), required: ["f", "pos"], additionalProperties: false },
99
+ description: "world pose at f; hand follows" },
100
+ fall: { ...FALL, description: "or a list; topic objects" },
101
+ follow: ref("ref"), offset: ref("vec3"), aim: { oneOf: [{ enum: ["face", "up"] }, { $ref: "#/$defs/vec3" }, { $ref: "#/$defs/ref" }], default: "up" },
102
+ };
103
+
104
+ export const CHECK_ENTRY_TYPES = {
105
+ name: str("the QA group's name"), point: ref("checkRef"), target: ref("checkRef"),
106
+ tol: num("m; default contacts 0.01, appear 0.035, supports 0.04"), when: ref("when"), from: ref("checkRef"), to: ref("checkRef"),
107
+ along: { oneOf: [{ enum: ["face", "up"] }, { $ref: "#/$defs/vec3" }] }, minCos: num("default 0.64"),
108
+ joint: str("bone"), ref: str("bone"), min: num("m; below default 0.08"), part: ref("part"),
109
+ object: str("scene object id"), frames: ref("frameSpan"), channel: str("a visibility channel"), anchor: str("an anchor name"), depth: num("allowed depth, m"),
110
+ };
111
+
112
+ /** Fields each checks entry must have. */
113
+ export const CHECK_REQUIRED = { contacts: ["point", "target"], orient: ["from", "to", "along"], below: ["joint", "ref"], clearance: ["part", "object", "min"],
114
+ appear: ["channel", "joint", "anchor"], supports: ["object"], allow: ["part", "object", "depth"] };
115
+
116
+ export const CHECKS_TYPES = {
117
+ limits: { type: "object", properties: Object.fromEntries(Object.entries(QA_LIMITS).map(([k, v]) => [k, num(null, { default: v })])), additionalProperties: false },
118
+ mouthPoints: { type: "array", items: str("prop.point"), description: "prop points allowed at the mouth" },
119
+ };
120
+
121
+ export const GOAL_TYPES = {
122
+ name: str(), near: pair({ $ref: "#/$defs/ref" }, "distance <= tol"), above: pair({ $ref: "#/$defs/ref" }, "a.y - b.y >= by"),
123
+ moved: str("a ref or an object id: an object's base moves at least `by` from the scene pose; any other point (prop:, joint:, landmark:, anchor:) at least `by` from where it is at at[0] (at: [f0, f1])"),
124
+ still: str("a ref or an object id: stays within `tol` of where moved measures from (an object: its scene pose; a point: where it is at at[0], at: [f0, f1])"),
125
+ speed: str("a point ref: its speed reaches `by` m/s (mode any by default)"),
126
+ tol: num("m; near default 0.05, still 0.01"), by: num("above m, default 0; moved m, default 0.05; speed m/s, needed"),
127
+ at: { oneOf: [int(null, { minimum: 0 }), { $ref: "#/$defs/frameSpan" }], description: "absolute frame or span" },
128
+ mode: { enum: ["all", "any"], description: "every frame of `at`, or one; default all, speed any" },
129
+ after: str("a goal's name: at starts after the first frame that goal holds"), before: str("a goal's name: at ends before the first frame that goal holds"),
130
+ };
131
+
132
+ export const PROBE_TYPES = {
133
+ name: str("the key of the answer"), distance: pair({ $ref: "#/$defs/ref" }, "min/max/mean/first/last m"), position: ref("ref", "world points"),
134
+ frames: ref("frameSpan", "absolute, default the whole take"), every: int("position: every n frames (<= 16 rows)", { minimum: 1 }),
135
+ };
136
+
137
+ export const FIX_TYPES = {
138
+ reach: bool("wrist targets past reach go onto it softly; hips lower for near-miss ankles", { default: true }),
139
+ slide: bool("lifts sunk soles; a planted heel or ball drifting under 1 cm stays put; a heel-up foot pivots on its ball", { default: true }),
140
+ penetration: { oneOf: [{ type: "boolean" }, { type: "number", minimum: 0, maximum: 0.05 }], default: 0, description: "push hands out of boxes up to this depth, m (true = 0.02)" },
141
+ self: bool("arms kept out of the body's skin (wrists, elbows)", { default: true }),
142
+ retime: bool("speed spikes borrow frames from the neighbouring keys", { default: false }),
143
+ };
144
+
145
+ export const REF_DOCS = {
146
+ joint: "joint:<Bone>", bone: "bone:<Bone> (= joint:)", prop: "prop:<prop>.<point> (origin exists)",
147
+ anchor: "anchor:<name>", landmark: "landmark:mouth", object: "object:<id>[.center|.top|.base], a body or group; bare = its surface (distance)",
148
+ person: "person:<id>.<Bone>",
149
+ };